26 #include <Classes.hpp>
27 #include <Controls.hpp>
28 #include <StdCtrls.hpp>
30 #include <Buttons.hpp>
31 #include <ExtCtrls.hpp>
33 #include <Dialogs.hpp>
34 #include <Graphics.hpp>
35 #include <ComCtrls.hpp>
53 #pragma package(smart_init)
72 TTrain::TTrain(
int Caller,
int RearStartElementIn,
int RearStartExitPosIn, AnsiString InputCode,
int StartSpeedIn,
int MassIn,
double MaxRunningSpeedIn,
73 double MaxBrakeRateIn,
double PowerAtRailIn,
TTrainMode TrainModeIn,
TTrainDataEntry *TrainDataEntryPtrIn,
int RepeatNumberIn,
int IncrementalMinutesIn,
74 int IncrementalDigitsIn,
int SignallerMaxSpeedIn) : RearStartElement(RearStartElementIn), RearStartExitPos(RearStartExitPosIn), HeadCode(InputCode),
75 StartSpeed(StartSpeedIn), Mass(MassIn), MaxRunningSpeed(MaxRunningSpeedIn), MaxBrakeRate(MaxBrakeRateIn), PowerAtRail(PowerAtRailIn),
76 TrainMode(TrainModeIn), TrainDataEntryPtr(TrainDataEntryPtrIn), RepeatNumber(RepeatNumberIn), IncrementalMinutes(IncrementalMinutesIn),
77 IncrementalDigits(IncrementalDigitsIn), SignallerMaxSpeed(SignallerMaxSpeedIn)
88 AnsiString(RearStartExitPosIn) +
"," + AnsiString(InputCode) +
"," + AnsiString(StartSpeedIn) +
"," + AnsiString(MassIn) +
"," +
89 AnsiString(TrainModeIn));
135 for(
int x = 0; x < 4; x++)
144 for(
int x = 0; x < 4; x++)
153 for(
int x = 0; x < 4; x++)
158 for(
int x = 0; x < 4; x++)
162 for(
int x = 0; x < 3; x++)
199 for(
int x = 0; x < 4; x++)
258 throw Exception(
"Error in attempting to delete FrontCodePtr");
262 for(
int x = 0; x < 4; x++)
266 throw Exception(
"Error in attempting to delete BackgroundPtr[" + AnsiString(x) +
"]");
271 for(
int x = 0; x < 4; x++)
275 throw Exception(
"Error in attempting to delete HeadCodeGrPtr[" + AnsiString(x) +
"]");
304 int NextElementPosition, NextEntryPos, ElementLength, SpeedLimit;
370 bool TempDerail =
false;
416 else if((NextElementPosition > -1) && (NextEntryPos > -1))
487 throw Exception(
"Error, LeadElement Exit Connection is NotSet");
497 for(
int x = 0; x < 4; x++)
504 for(
int x = 0; x < 4; x++)
765 int LockedVectorNumber;
894 AnsiString ReasonArray[24] = {
"a driver is awaited",
"a guard is awaited",
"of a medical emergency",
"of a technical problem",
"of a security issue",
895 "of a safety issue",
"of a disturbance",
"a train crew member has been taken ill",
"the driver has been taken ill",
"the guard has been taken ill",
896 "a report has been received concerning safety",
"a shoe has been lost under the train",
"of a reported theft",
897 "of an incident involving an animal",
"some luggage has been lost under the train",
"a minor repair is needed",
"a suspicious object has to be dealt with safely",
898 "a door is stuck open",
"additional stock has to be attached",
"a security alert",
"of a train fault",
"of an operating incident",
"safety checks are required",
899 "of a shortage of on train crew"};
906 if(DwellTime < TDateTime(30.0 / 86400))
908 DwellTime = TDateTime(30.0 / 86400);
910 int randval = random(10000);
915 if(randval < Utilities->MinorDelayCutoff)
922 if(randval < Utilities->ModerateDelayCutoff)
929 if(randval < Utilities->MajorDelayCutoff)
944 if(
NewDelay <
double(DwellTime) * 1440)
950 NewDelay -= double(DwellTime) * 1440;
1009 int randval2 = rand() % 24;
1010 AnsiString Reason = ReasonArray[randval2];
1013 " minutes because " + Reason);
1019 " minutes because of a minor problem");
1162 if(BufferLocation ==
"")
1167 if((BufferLocation ==
"") || (BufferLocation != ExpectedLocation))
1229 int NextElementPosition, NextEntryPos;
1253 NextElementPosition = -1;
1256 if((NextElementPosition > -1) && (NextEntryPos > -1))
1374 AnsiString StationName;
1385 throw Exception(
"Error - Stopped at through station but neither lead nor mid elements have a name");
1398 if((NextElementPosition > -1) && (NextEntryPos > -1))
1532 if(TIFEntryPos == 0)
1568 if(NextElementPosition > -1)
1605 AnsiString Loc =
"";
1606 bool LocNamed =
false;
1635 Loc =
"outside railway";
1667 NextElementPosition = -1;
1678 if((NextElementPosition > -1) && (NextEntryPos > -1) && !
SPADFlag)
1696 if((NextElementPosition > -1) && (NextEntryPos > -1))
1734 FirstPair.second).
GetELink() == TempELink))
1739 SecondPair.second).
GetELink() == TempELink))
1753 FirstPair.second).
GetELink() == TempELink))
1758 SecondPair.second).
GetELink() == TempELink))
1772 FirstPair.second).
GetELink() == TempELink))
1777 SecondPair.second).
GetELink() == TempELink))
1807 ContinuationAutoSigEntry.
RouteNumber = RouteNumber;
1810 int NewLastElement = 0, NewLastExitPos = 0;
1828 if(NewLastElement == -1)
1831 throw Exception(
"Error, Connection = -1 in Continuation loop in UpdateTrain");
1834 if(NewLastExitPos == -1)
1836 throw Exception(
"Error, ConnLinkPos = -1 in Continuation loop in UpdateTrain");
1838 LastElement = NewLastElement;
1839 LastExitPos = NewLastExitPos;
1842 if(CumDistance < 1200)
1848 int FirstDistance = 0;
1849 if(CumDistance >= 1200)
1851 FirstDistance = 100;
1855 FirstDistance = 1200 - CumDistance;
1857 if(FirstDistance < 100)
1859 FirstDistance = 100;
1885 if(VectorIT->RouteNumber == RouteNumber)
1922 " failed when changing aspect.\nTrains can only pass under signaller control.");
1956 LockedVectorNumber)))
2115 for(
int x = 0; x < 4; x++)
2122 for(
int x = 0; x < 4; x++)
2148 if((LeadElementTrainID > -1) && (LeadElementTrainID !=
TrainID))
2153 if(OtherTrainEntryPos == -1)
2155 throw Exception(
"Error - OtherTrainEntryPos not set");
2174 int OtherTrainID = -1;
2175 if((MidExitLinkNum == 1) || (MidExitLinkNum == 3) || (MidExitLinkNum == 7) || (MidExitLinkNum == 9))
2266 bool StopRequired =
false;
2279 int NextElementEntryPos = -1;
2280 int NextElementExitPos = -1;
2281 bool TrainOnNextElement =
false;
2282 bool StopSignalAtNextElement =
false;
2283 if(ForwardConnection)
2291 StopSignalAtNextElement = ((NextTrackElement.
Config[NextElementExitPos] ==
Signal) && (NextTrackElement.
Attribute == 0));
2293 if(TrainAtStopLinkPos1 || TrainAtStopLinkPos2 || (ForwardConnection && (TrainOnNextElement || StopSignalAtNextElement)))
2349 throw Exception(
"Error, Straddle shouldn't be LeadMid prior to resetting at exit from UpdateTrain");
2562 if(Code.Length() != 4)
2566 for(
int x = 1; x < 5; x++)
2573 for(
int x = 0; x < 4; x++)
2736 throw Exception(
"Error in GetOffsetValues - Link value wrong");
2749 if((EntryLink == 1) || (EntryLink == 2) || (EntryLink == 4) || (EntryLink == 7))
2764 AnsiString(
VOffset) +
"," + AnsiString(Element) +
"," + AnsiString(EntryPos) +
"," +
HeadCode);
2773 TRect SourceRect, DestRect;
2775 DestRect.init(0, 0, 8, 8);
2778 Graphics::TBitmap *TempGraphic =
new Graphics::TBitmap;
2780 TempGraphic->PixelFormat = pf8bit;
2781 TempGraphic->Width = 16;
2782 TempGraphic->Height = 16;
2788 TempGraphic->Transparent =
true;
2792 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2793 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2799 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2807 else if(TempElement.
SpeedTag == 89)
2811 else if(TempElement.
SpeedTag == 90)
2815 else if(TempElement.
SpeedTag == 91)
2819 else if(TempElement.
SpeedTag == 92)
2823 else if(TempElement.
SpeedTag == 93)
2827 else if(TempElement.
SpeedTag == 94)
2831 else if(TempElement.
SpeedTag == 95)
2835 TempGraphic->Transparent =
true;
2839 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2840 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2842 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2849 for(
int x = 0; x < 40; x++)
2864 TempGraphic->Transparent =
true;
2868 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2869 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2871 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2885 TempGraphic->Transparent =
true;
2889 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2890 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2894 TempGraphic->Canvas->Draw(0, 0, TempElement.
GraphicPtr);
2897 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2902 TempGraphic->Transparent =
true;
2906 int BDVectorPos = -1;
2915 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2920 TempGraphic->Transparent =
true;
2924 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2925 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2927 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2933 TempGraphic->Transparent =
true;
2937 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2938 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2940 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3206 throw Exception(
"Error, same train on two different bridge tracks");
3252 AnsiString(EntryPos) +
"," +
HeadCode);
3269 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in SetTrainElementID");
3288 AnsiString(EntryPos) +
"," +
HeadCode);
3297 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in ResetTrainElementID");
3330 AnsiString(ElementEntryPos) +
"," + AnsiString(
HOffset) +
"," + AnsiString(
VOffset) +
"," + AnsiString(StraddleValue) +
"," +
HeadCode);
3331 int LockedVectorNumber;
3344 TRect SourceRect, DestRect;
3345 DestRect.init(0, 0, 8, 8);
3352 int FirstELink, SecondELink = -1;
3355 if(RoutePair2.first > -1)
3364 if(SecondELink == -1)
3366 throw Exception(
"Error - Second ELink should be set but isn't in PlotAlternativeTrackRouteGraphic [1]");
3371 throw Exception(
"Error - First & Second ELinks have same value in PlotAlternativeTrackRouteGraphic");
3381 Graphics::TBitmap *DestGraphic =
new Graphics::TBitmap;
3382 DestGraphic->PixelFormat = pf8bit;
3383 DestGraphic->Width = 8;
3384 DestGraphic->Height = 8;
3385 DestGraphic->Transparent =
true;
3388 DestGraphic->Canvas->CopyRect(DestRect, RouteElement.
GetRouteEXGraphicPtr()->Canvas, SourceRect);
3397 PrefDirElement, LockedVectorNumber))
3412 if(ElementEntryPos > 1)
3434 AnsiString(EntryPos) +
"," +
HeadCode);
3436 bool WrongRoute =
false;
3462 int LinkNumber = TrackElement.
Link[EntryPos];
3463 if((LinkNumber == 1) || (LinkNumber == 3) || (LinkNumber == 7) || (LinkNumber == 9))
3468 bool LogActionErrorCalled =
false;
3478 LogActionErrorCalled =
true;
3495 else if(LinkNumber == 3)
3503 LogActionErrorCalled =
true;
3520 else if(LinkNumber == 7)
3528 LogActionErrorCalled =
true;
3545 else if(LinkNumber == 9)
3553 LogActionErrorCalled =
true;
3585 else if((RouteElement.
GetELinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3590 else if((RouteElement.
GetELinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3600 else if((RouteElement.
GetXLinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3605 else if((RouteElement.
GetXLinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3614 throw Exception(
"Error, Element in route but no route found in CheckAndCancelRouteForWrongEndEntry");
3635 bool ColourError =
false, ColourError2 =
false;
3640 ColourError2 =
true;
3642 for(
int x = 0; x < 4; x++)
3647 ColourError2 =
true;
3653 "ERROR: Colour depth insufficient to display train colours properly. Please ensure that the 'safe' (web) palette of 256 colours can be displayed");
3657 for(
int x = 0; x < 4; x++)
3744 AnsiString(EntryPos) +
"," +
HeadCode);
3745 int EntryHalfLength, CurrentElementHalfLength, NextElementHalfLength, CumulativeLength = 0, CurrentTrackVectorPosition = TrackVectorPosition;
3746 int DistanceAtHalfBraking, DistanceAtThreeQuarterBraking, ExitPos, NextTrackVectorPosition, NextEntryPos;
3747 bool RedSignalFlag =
false, BuffersFlag =
false, StationFlag =
false, BuffersOrContinuationNowFlag =
false, ContinuationNextFlag =
false,
3748 TrainInFrontInSignallerModeFlag =
false;
3749 double LimitingSpeed, FrontElementMaxSpeed, MaxExitSpeedAtHalfBrakingSquared, MaxExitSpeedAtHalfBraking, NextSpeedLimit, TempBrakeRate;
3750 double ExitSpeedHalfSquared, ExitSpeedFullSquared;
3751 bool SignallerStopRequired =
false;
3762 if(CurrentTrackVectorPosition > -1)
3766 if((EntryPos == 0) || (EntryPos == 2))
3779 else if(EntryPos == 1)
3803 EntryHalfLength = CurrentElementHalfLength;
3808 throw Exception(
"Error - CurrentTrackVectorPosition < 0 in SetTrainMovementValues");
3812 throw Exception(
"Error - HalfLength or SpeedLimit < 0 in SetTrainMovementValues");
3859 FrontElementMaxSpeed = LimitingSpeed;
3894 double ExitSpeedAtMaxBraking;
3899 ExitSpeedAtMaxBraking = 0;
3909 if(ExitSpeedAtMaxBraking > LimitingSpeed)
3911 SpeedToUse = ExitSpeedAtMaxBraking;
3915 SpeedToUse = LimitingSpeed;
3930 RedSignalFlag =
false;
3931 BuffersFlag =
false;
3932 StationFlag =
false;
3933 BuffersOrContinuationNowFlag =
false;
3934 ContinuationNextFlag =
false;
3937 CumulativeLength += (2 * CurrentElementHalfLength);
3940 SignallerStopRequired =
true;
3962 bool StopRequired =
false;
3976 StationFlag =
false;
3982 BuffersOrContinuationNowFlag =
true;
3984 if(!BuffersOrContinuationNowFlag && !BuffersFlag && !StationFlag)
3988 if((EntryPos == 0) || (EntryPos == 2))
4010 if(NextTrackVectorPosition > -1)
4015 if((NextEntryPos == 0) || (NextEntryPos == 2))
4028 else if(NextEntryPos == 1)
4041 if(NextEntryPos > 1)
4055 throw Exception(
"Error - Trying to access NextTrackVectorPosition when none present in SetTrainMovementValues");
4067 RedSignalFlag =
true;
4089 TrainInFrontInSignallerModeFlag =
true;
4113 if(RedSignalFlag || BuffersFlag || StationFlag || TrainInFrontInSignallerModeFlag || SignallerStopRequired ||
StepForwardFlag)
4125 double MaxHalfSpeed;
4129 if(MaxHalfSpeedAtHalfBraking > FrontElementMaxSpeed)
4131 MaxHalfSpeed = FrontElementMaxSpeed;
4135 MaxHalfSpeed = MaxHalfSpeedAtHalfBraking;
4143 bool HalfSpeedLimited =
false;
4147 HalfSpeedLimited =
true;
4177 if(HalfSpeedLimited)
4202 if(SignallerStopRequired)
4218 int TempMaxExitSpeed;
4221 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4223 MaxExitSpeedAtHalfBraking = 0;
4227 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4231 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4233 TempMaxExitSpeed = FrontElementMaxSpeed;
4237 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4249 if(ExitSpeedHalfSquared < 10)
4259 if(ExitSpeedFullSquared < 10)
4331 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4332 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4356 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4357 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4367 if(!BuffersOrContinuationNowFlag)
4369 if(NextSpeedLimit < LimitingSpeed)
4371 LimitingSpeed = NextSpeedLimit;
4375 int TempMaxExitSpeed;
4379 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4381 MaxExitSpeedAtHalfBraking = 0;
4385 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4387 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4389 TempMaxExitSpeed = FrontElementMaxSpeed;
4393 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4404 TempBrakeRate = ((
EntrySpeed *
EntrySpeed) - (LimitingSpeed * LimitingSpeed)) / 3.6 / 3.6 / 2 / CumulativeLength;
4417 if(!BuffersOrContinuationNowFlag)
4419 CurrentTrackVectorPosition = NextTrackVectorPosition;
4420 EntryPos = NextEntryPos;
4421 CurrentElementHalfLength = NextElementHalfLength;
4424 ContinuationNextFlag =
true;
4428 while(((CumulativeLength -
FrontElementLength) < DistanceAtHalfBraking) && ((!BuffersOrContinuationNowFlag && !ContinuationNextFlag) ||
4448 if(ExitSpeedHalfSquared < 10)
4458 if(ExitSpeedFullSquared < 10)
4521 double DeltaExitTimeToMaxInSecs;
4522 double DistanceToMax;
4531 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4533 DistanceToMax = EntryHalfLength;
4536 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4537 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4554 double DeltaExitTimeToMaxInSecs;
4555 double DistanceToMax;
4564 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4566 DistanceToMax = EntryHalfLength / 2;
4569 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4570 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4581 if(ExitSpeedHalfSquared < 10)
4591 if(ExitSpeedFullSquared < 10)
4610 if((EntryPos == 0) || (EntryPos == 2))
4632 if(NextTrackVectorPosition > -1)
4634 int NextElementLength;
4635 if(NextEntryPos > 1)
4643 double NextStoppingSpeed = sqrt(3.6 * 3.6 * 2 *
BrakeRate * NextElementLength);
4830 int ElementCount = 0;
4838 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition;
4856 CurrentTrackVectorPosition).
Attribute != 4))
4896 if((EntryPos == 0) || (EntryPos == 2))
4918 CurrentTrackVectorPosition = NextTrackVectorPosition;
4919 EntryPos = NextEntryPos;
4921 if(ElementCount > 1000)
4949 throw Exception(
"Error - failed to set ReturnVal in ClearToNextSignal()");
4974 bool PlatformFoundFlag =
false, StopRequired =
false, SkipRouteCheck =
false, RouteOrPartRouteSet =
false;
4975 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition, ElementNumber = 0, Distance = 0;
4976 int RouteStartPosition;
4978 int PlatformPosition;
4980 int EntryPos =
LeadEntryPos, ExitPos, NextEntryPos, RouteID;
4996 if(Distance > (4000 + LeadElementDistance))
5019 if(OtherTrain.
LeadElement == CurrentTrackVectorPosition)
5022 if((OtherCommand ==
"Fjo") || (OtherCommand ==
"jbo") || (OtherCommand ==
"cdt") || (OtherCommand ==
"Frh") ||
5068 if(!PlatformFoundFlag)
5070 PlatformPosition = CurrentTrackVectorPosition;
5073 PlatformFoundFlag =
true;
5089 if((EntryPos == 0) || (EntryPos == 2))
5133 if(ElementNumber < 2)
5135 SkipRouteCheck =
true;
5139 SkipRouteCheck =
false;
5141 if(ElementNumber == 1)
5143 RouteStartPosition = CurrentTrackVectorPosition;
5153 if(ElementNumber > 1)
5157 RouteOrPartRouteSet =
true;
5161 RouteOrPartRouteSet =
false;
5164 if(!SkipRouteCheck && !RouteOrPartRouteSet)
5171 int ExitLink = CurrentTrackElement.
Link[ExitPos];
5172 if((ExitLink == 1) || (ExitLink == 3) || (ExitLink == 7) || (ExitLink == 9))
5184 Distance += CurrentTrackElement.
Length01;
5188 Distance += CurrentTrackElement.
Length23;
5190 NextTrackVectorPosition = CurrentTrackElement.
Conn[ExitPos];
5191 NextEntryPos = CurrentTrackElement.
ConnLinkPos[ExitPos];
5192 CurrentTrackVectorPosition = NextTrackVectorPosition;
5193 EntryPos = NextEntryPos;
5230 return(RepeatHeadCode);
5252 bool FrontValid =
false, RearValid =
false;
5253 TTrackElement FrontAdjacentTrackElement, RearAdjacentTrackElement;
5257 TrainToBeJoinedBy = NULL;
5271 int TrainToBeJoinedByID = -1;
5292 if((TrainToBeJoinedByID < 0) && RearValid)
5311 if(TrainToBeJoinedByID < 0)
5313 TrainToBeJoinedBy = NULL;
5318 if(!TrainToBeJoinedBy->
Stopped())
5320 TrainToBeJoinedBy = NULL;
5331 TDateTime TimetableNonRepeatTime,
bool Warning)
5366 AnsiString(ActionType) +
"," + LocationName +
"," +
HeadCode);
5367 AnsiString BaseLog =
"", WarningBaseLog =
"", PerfLog =
"", ActionLog =
"";
5368 int IntMinsLate = 0;
5373 ActionLog =
" arrived at ";
5382 ActionLog =
" terminated at ";
5387 ActionLog =
" departed from ";
5389 if(ActionType ==
Pass)
5391 ActionLog =
" passed ";
5395 ActionLog =
" created at ";
5397 if(ActionType ==
Enter)
5399 ActionLog =
" entered railway at ";
5401 if(ActionType ==
Leave)
5403 ActionLog =
" left railway at ";
5407 ActionLog =
" split from front to ";
5411 ActionLog =
" split from rear to ";
5415 ActionLog =
" joined by ";
5419 ActionLog =
" changed direction at ";
5423 ActionLog =
" became new service ";
5427 ActionLog =
" taken under signaller control at ";
5431 ActionLog =
" restored to timetable control at ";
5437 ActionLog =
" REMOVED FROM RAILWAY DUE TO CRASH at ";
5441 ActionLog =
" REMOVED FROM RAILWAY DUE TO DERAILMENT at ";
5445 ActionLog =
" REMOVED FROM RAILWAY at ";
5450 ActionLog =
" received signaller authority to proceed";
5454 ActionLog =
" received signaller authority to step forward";
5458 ActionLog =
" changed direction under signaller control at ";
5462 ActionLog =
" received signaller authority to pass stop signal";
5466 ActionLog =
" received signaller instruction to stop";
5470 ActionLog =
" stopped on signaller instruction ";
5474 ActionLog =
" joined under signaller control by ";
5478 ActionLog =
" suffered an onboard power failure at ";
5482 ActionLog =
" failure repaired at ";
5486 ActionLog =
" left railway under signaller control at ";
5488 if(OtherHeadCode !=
"")
5490 OtherHeadCode +=
" at ";
5503 bool TimePerformance =
true;
5511 TimePerformance =
false;
5515 double MinsLate = ((double)(ActualTime -
GetTrainTime(1, TimetableNonRepeatTime))) * 1440;
5517 if(ActionType ==
Pass)
5531 IntMinsLate = int(ceil(MinsLate));
5535 IntMinsLate = int(floor(MinsLate));
5537 if(IntMinsLate == 0)
5539 PerfLog =
" on time";
5541 else if(IntMinsLate == 1)
5543 PerfLog =
" 1 minute late";
5545 else if(IntMinsLate == -1)
5547 PerfLog =
" 1 minute early";
5549 else if(IntMinsLate > 1)
5551 PerfLog =
" " + AnsiString(IntMinsLate) +
" minutes late";
5553 else if(IntMinsLate < -1)
5555 int PosIntMinsLate = -IntMinsLate;
5556 PerfLog =
" " + AnsiString(PosIntMinsLate) +
" minutes early";
5558 if(LocationName.Pos(
'-') > 0)
5560 PerfLog =
"," + PerfLog;
5574 if((ActionType ==
Arrive) && (IntMinsLate == 0))
5578 else if((ActionType ==
Arrive) && (IntMinsLate > 0))
5583 else if((ActionType ==
Arrive) && (IntMinsLate < 0))
5589 else if((ActionType ==
Pass) && (IntMinsLate == 0))
5593 else if((ActionType ==
Pass) && (IntMinsLate > 0))
5598 else if((ActionType ==
Pass) && (IntMinsLate < 0))
5604 else if((ActionType ==
Leave) && (IntMinsLate == 0))
5608 else if((ActionType ==
Leave) && (IntMinsLate > 0))
5613 else if((ActionType ==
Leave) && (IntMinsLate < 0))
5619 else if((ActionType ==
Depart) && (IntMinsLate == 0))
5623 else if((ActionType ==
Depart) && (IntMinsLate > 0))
5642 AnsiString LocName =
"";
5709 if(LocationName ==
"")
5713 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
5714 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
5715 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
5719 if(LocationName !=
"")
5727 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5732 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5746 int LeadPosA = FirstNamedElementPos;
5747 int LeadPosB = FirstNamedLinkedElementPos;
5748 int LeadPosC = SecondNamedElementPos;
5749 int LeadPosD = SecondNamedLinkedElementPos;
5751 int LeadNumAtLoc = 0;
5768 if(LeadNumAtLoc < 4)
5772 SecondNamedLinkedElementPos))
5774 FirstNamedElementPos = LeadPosA;
5775 FirstNamedLinkedElementPos = LeadPosB;
5776 SecondNamedElementPos = LeadPosC;
5777 SecondNamedLinkedElementPos = LeadPosD;
5781 int MidNumAtLoc = 0;
5798 if(LeadNumAtLoc > MidNumAtLoc)
5801 FirstNamedElementPos = LeadPosA;
5802 FirstNamedLinkedElementPos = LeadPosB;
5803 SecondNamedElementPos = LeadPosC;
5804 SecondNamedLinkedElementPos = LeadPosD;
5818 throw Exception(
"Error - LocationName not set in FrontTrainSplit");
5828 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5829 FrontTrainRearPosition = FirstNamedElementPos;
5830 RearTrainFrontPosition = SecondNamedElementPos;
5831 RearTrainRearPosition = SecondNamedLinkedElementPos;
5835 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5836 FrontTrainRearPosition = SecondNamedElementPos;
5837 RearTrainFrontPosition = FirstNamedElementPos;
5838 RearTrainRearPosition = FirstNamedLinkedElementPos;
5845 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5846 FrontTrainRearPosition = SecondNamedElementPos;
5847 RearTrainFrontPosition = FirstNamedElementPos;
5848 RearTrainRearPosition = FirstNamedLinkedElementPos;
5852 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5853 FrontTrainRearPosition = FirstNamedElementPos;
5854 RearTrainFrontPosition = SecondNamedElementPos;
5855 RearTrainRearPosition = SecondNamedLinkedElementPos;
5858 RearTrainExitPos = -1;
5859 for(
int x = 0; x < 4; x++)
5863 RearTrainExitPos = x;
5867 if(RearTrainExitPos == -1)
5869 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in FrontTrainSplit");
5871 FrontTrainExitPos = -1;
5872 for(
int x = 0; x < 4; x++)
5876 FrontTrainExitPos = x;
5880 if(FrontTrainExitPos == -1)
5882 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in FrontTrainSplit");
5885 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
5892 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
5912 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
5920 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
5921 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
5922 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
6019 if(LocationName ==
"")
6023 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
6024 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
6025 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
6029 if(LocationName !=
"")
6036 SecondNamedLinkedElementPos))
6040 SecondNamedLinkedElementPos))
6054 int LeadPosA = FirstNamedElementPos;
6055 int LeadPosB = FirstNamedLinkedElementPos;
6056 int LeadPosC = SecondNamedElementPos;
6057 int LeadPosD = SecondNamedLinkedElementPos;
6059 int LeadNumAtLoc = 0;
6076 if(LeadNumAtLoc < 4)
6080 SecondNamedLinkedElementPos))
6082 FirstNamedElementPos = LeadPosA;
6083 FirstNamedLinkedElementPos = LeadPosB;
6084 SecondNamedElementPos = LeadPosC;
6085 SecondNamedLinkedElementPos = LeadPosD;
6089 int MidNumAtLoc = 0;
6106 if(LeadNumAtLoc > MidNumAtLoc)
6109 FirstNamedElementPos = LeadPosA;
6110 FirstNamedLinkedElementPos = LeadPosB;
6111 SecondNamedElementPos = LeadPosC;
6112 SecondNamedLinkedElementPos = LeadPosD;
6126 throw Exception(
"Error - LocationName not set in RearTrainSplit");
6136 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
6137 FrontTrainRearPosition = FirstNamedElementPos;
6138 RearTrainFrontPosition = SecondNamedElementPos;
6139 RearTrainRearPosition = SecondNamedLinkedElementPos;
6143 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
6144 FrontTrainRearPosition = SecondNamedElementPos;
6145 RearTrainFrontPosition = FirstNamedElementPos;
6146 RearTrainRearPosition = FirstNamedLinkedElementPos;
6153 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
6154 FrontTrainRearPosition = SecondNamedElementPos;
6155 RearTrainFrontPosition = FirstNamedElementPos;
6156 RearTrainRearPosition = FirstNamedLinkedElementPos;
6160 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
6161 FrontTrainRearPosition = FirstNamedElementPos;
6162 RearTrainFrontPosition = SecondNamedElementPos;
6163 RearTrainRearPosition = SecondNamedLinkedElementPos;
6166 RearTrainExitPos = -1;
6167 for(
int x = 0; x < 4; x++)
6171 RearTrainExitPos = x;
6175 if(RearTrainExitPos == -1)
6177 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in RearTrainSplit");
6179 FrontTrainExitPos = -1;
6180 for(
int x = 0; x < 4; x++)
6184 FrontTrainExitPos = x;
6188 if(FrontTrainExitPos == -1)
6190 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in RearTrainSplit");
6193 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
6200 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
6220 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
6228 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
6229 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
6230 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
6374 TTrain *TrainToBeJoinedBy;
6407 double OtherBrakeForce = TrainToBeJoinedBy->
MaxBrakeRate * TrainToBeJoinedBy->
Mass;
6409 double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->
Mass +
Mass);
6470 int RouteNumber = -1;
6475 int CorrectRouteID = OR.
RouteID;
6480 bool FirstPass =
true;
6485 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6592 for(
int x = 0; x < IncNum; x++)
6625 else if(Ptr->
Command ==
"jbo")
6636 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6642 bool IncludeFER =
false;
6650 if(!IncludeFER && (Ptr->
Command ==
"Fer"))
6655 else if(IncludeFER && (Ptr->
Command ==
"Fer"))
6666 else if(Ptr->
Command ==
"Fjo")
6672 else if(Ptr->
Command ==
"Frh")
6682 else if(Ptr->
Command ==
"Frh-sh")
6733 else if(Ptr->
Command ==
"jbo")
6738 else if(Ptr->
Command ==
"cdt")
6746 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
7133 int RouteNumber = -1;
7138 int CorrectRouteID = OR.
RouteID;
7143 bool FirstPass =
true;
7148 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
7176 ",FloatingLabelNextString" +
"," +
HeadCode);
7177 AnsiString RetStr =
"", LocationName =
"";
7180 if(ActionTime == TDateTime(-1))
7184 if(ActionTime == TDateTime(-1))
7190 if(ActionTime != TDateTime(-1))
7198 throw Exception(
"Error - start entry in FloatingLabelNextString");
7242 else if(Ptr->
Command ==
"Fns")
7248 else if(Ptr->
Command ==
"F-nshs")
7279 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7281 else if(Ptr->
Command ==
"Frh")
7283 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7285 else if(Ptr->
Command ==
"Fer")
7287 AnsiString AllowedExits =
"";
7290 else if(Ptr->
Command ==
"Fjo")
7295 else if(Ptr->
Command ==
"jbo")
7300 else if(Ptr->
Command ==
"fsp")
7305 else if(Ptr->
Command ==
"rsp")
7310 else if(Ptr->
Command ==
"cdt")
7319 throw Exception(
"Error - start entry in FloatingLabelNextString where TTClockTime > ActionTime");
7363 else if(Ptr->
Command ==
"Fns")
7369 else if(Ptr->
Command ==
"F-nshs")
7400 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7402 else if(Ptr->
Command ==
"Frh")
7404 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7406 else if(Ptr->
Command ==
"Fer")
7408 AnsiString AllowedExits =
"";
7411 else if(Ptr->
Command ==
"Fjo")
7416 else if(Ptr->
Command ==
"jbo")
7421 else if(Ptr->
Command ==
"fsp")
7426 else if(Ptr->
Command ==
"rsp")
7431 else if(Ptr->
Command ==
"cdt")
7440 throw Exception(
"Error - start entry in FloatingLabelNextString in final 'else'");
7484 else if(Ptr->
Command ==
"Fns")
7490 else if(Ptr->
Command ==
"F-nshs")
7521 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7523 else if(Ptr->
Command ==
"Frh")
7525 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7527 else if(Ptr->
Command ==
"Fer")
7529 AnsiString AllowedExits =
"";
7532 else if(Ptr->
Command ==
"Fjo")
7537 else if(Ptr->
Command ==
"jbo")
7542 else if(Ptr->
Command ==
"fsp")
7547 else if(Ptr->
Command ==
"rsp")
7552 else if(Ptr->
Command ==
"cdt")
7696 + AnsiString(RptNum) +
",GetNewServiceDepartureInfo," +
HeadCode);
7697 AnsiString DepTime =
"", EventTime =
"";
7698 bool CDTFlag =
false;
7700 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
7701 AnsiString TowardsLocation =
"";
7704 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
7706 TowardsLocation = AVI->LocationName;
7708 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
7717 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
7724 if(AVI->Command ==
"cdt")
7729 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
7744 RetStr +=
"\nNew service splits at approx. " + EventTime;
7748 if(AVI->Command ==
"jbo")
7763 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at approx. " + EventTime;
7767 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
7774 if(TowardsLocation !=
"")
7776 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
7780 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
7785 if(TowardsLocation !=
"")
7787 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
7791 RetStr +=
"\nNew service departs at " + DepTime;
7800 if(TowardsLocation !=
"")
7802 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
7806 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
7811 if(TowardsLocation !=
"")
7813 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
7817 RetStr +=
"\nNew service departs at approx. " + DepTime;
7834 if(TowardsLocation !=
"")
7836 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
7840 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
7845 if(TowardsLocation !=
"")
7847 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
7851 RetStr +=
"\nNew service departs at approx. " + DepTime;
7870 ",FloatingTimetableString" +
"," +
HeadCode);
7871 AnsiString RetStr =
"", PartStr =
"";
7873 bool SkipDep =
false, SkipDepActedOn =
false;
7879 throw Exception(
"Error - start entry in FloatingTimetableString");
7882 bool FirstPass =
true;
7895 AnsiString TrainLoc =
"";
7941 AnsiString TrainLoc =
"";
7981 else if(Ptr->
Command ==
"Fns")
7987 else if(Ptr->
Command ==
"F-nshs")
8020 else if(Ptr->
Command ==
"Frh")
8024 else if(Ptr->
Command ==
"Fer")
8026 AnsiString AllowedExits =
"";
8029 else if(Ptr->
Command ==
"Fjo")
8034 else if(Ptr->
Command ==
"jbo")
8039 else if(Ptr->
Command ==
"fsp")
8044 else if(Ptr->
Command ==
"rsp")
8049 else if(Ptr->
Command ==
"cdt")
8055 RetStr = RetStr +
'\n' + PartStr;
8069 SkipDepActedOn =
true;
8080 RetStr =
"Timetable finished";
8084 RetStr =
"No timetable";
8088 return(
"Timetable:\n" + RetStr);
8241 bool ForwardHeadCode;
8245 ForwardHeadCode =
true;
8250 ForwardHeadCode =
false;
8393 if(ColourNumber == 0)
8397 else if(ColourNumber == 1)
8401 else if(ColourNumber == 2)
8405 else if(ColourNumber == 3)
8409 else if(ColourNumber == 4)
8413 else if(ColourNumber == 5)
8417 else if(ColourNumber == 6)
8421 else if(ColourNumber == 7)
8425 else if(ColourNumber == 8)
8429 else if(ColourNumber == 9)
8433 else if(ColourNumber == 10)
8437 else if(ColourNumber == 11)
8441 else if(ColourNumber == 12)
8445 else if(ColourNumber == 13)
8449 else if(ColourNumber == 14)
8461 for(
int x = 0; x < 4; x++)
8468 for(
int x = 0; x < 4; x++)
8553 if((LocationAndMarker[1] !=
'*') && (LocationAndMarker.Length() > 6))
8556 AnsiString Location = LocationAndMarker.SubString(1, LocationAndMarker.Length() - 6);
8557 bool GiveMessagesFalse =
false;
8558 bool CheckLocationsExistInRailwayTrue =
true;
8565 AnsiString Marker = LocationAndMarker.SubString(LocationAndMarker.Length() - 5, 6);
8568 if(Marker[6] ==
'1')
9033 bool HideFlashingTrain =
true;
9036 Graphics::TBitmap *SmallTrainBitmap;
9077 HideFlashingTrain =
false;
9082 HideFlashingTrain =
false;
9087 HideFlashingTrain =
false;
9092 HideFlashingTrain =
false;
9097 HideFlashingTrain =
false;
9101 if((
LeadElement > -1) && (!HideFlashingTrain || Flash))
9105 if((
MidElement > -1) && (!HideFlashingTrain || Flash))
9129 for(
int y = 0; y < 3; y++)
9133 bool FoundFlag =
false;
9144 if(IMPair.first != IMPair.second)
9171 if((LocationName ==
"") && (
MidElement > -1))
9175 if((LocationName ==
"") && (
LagElement > -1))
9179 if(LocationName ==
"")
9181 throw Exception(
"Error - Location name not set in TrainAtLocation");
9192 for(
int x = 0; x < 4; x++)
9204 for(
int x = 0; x < 4; x++)
9221 AnsiString(LinkNumber) +
"," +
HeadCode);
9273 int DistanceToRedSignal = 0, DistanceToExit = -1;
9274 float TimeToAct = 0, LastTimeToExit =
TimeToExit;
9278 float MinsEarly = 0;
9279 TDateTime DepartureTime;
9280 TDateTime ArrivalTime;
9308 if(TempTTE < LastTimeToExit)
9343 if(TempTTE < LastTimeToExit)
9366 if(TempTTE < LastTimeToExit)
9396 if(TempTTE < LastTimeToExit)
9419 if(TempTTE < LastTimeToExit)
9462 float CurrentStopTime;
9463 float LaterStopTime;
9464 float RecoverableTime;
9472 if((DistanceToRedSignal == -1) && (DistanceToExit == -1))
9479 bool DistanceToRedSignalSet = (DistanceToRedSignal > -1);
9480 bool DistanceToExitSet = (DistanceToExit > -1);
9481 int GenericDistance = DistanceToRedSignal;
9482 if(DistanceToExitSet)
9484 GenericDistance = DistanceToExit;
9500 float TimeToSubtract, TotalStopTime;
9503 TimeToSubtract = RecoverableTime;
9546 if(CurrentStopTime > 0)
9548 TotalStopTime = CurrentStopTime + LaterStopTime;
9557 else if((MinsEarly > 0) && !
Stopped())
9559 TotalStopTime = LaterStopTime + MinsEarly;
9563 if(LaterStopTime == 0)
9565 TotalStopTime = CurrentStopTime;
9571 TotalStopTime = CurrentStopTime + LaterStopTime - TimeToSubtract;
9574 if(AvTrackSpeed < 30)
9578 int Speed = AvTrackSpeed;
9588 if(DistanceToRedSignalSet)
9590 TimeToAct = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9600 TimeToExit = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9629 if((NextEntryPos == 0) || (NextEntryPos == 2))
9756 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9798 int IncrementalMinutes = 0;
9799 int IncrementalDigits = 0;
9807 throw Exception(
"Error - Repeat entry && less than two trains for Snt entry: " + TDEntry.
HeadCode);
9842 if(AVEntry0.
Command ==
"Snt-sh")
9847 int IncrementalMinutes = 0;
9848 int IncrementalDigits = 0;
9856 throw Exception(
"Error - Repeat entry && less than two trains for Snt-sh entry: " + TDEntry.
HeadCode);
9899 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9979 AnsiString Loc =
"";
9980 bool ElementFound =
false;
9985 ElementFound =
true;
9990 ElementFound =
true;
9995 ElementFound =
true;
10024 else if(AVEntryPtr->
Command ==
"Fer")
10026 bool CorrectExit =
false;
10033 CorrectExit =
true;
10138 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10156 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10171 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10182 bool TTrainController::AddTrain(
int Caller,
int RearPosition,
int FrontPosition, AnsiString HeadCode,
int StartSpeed,
int Mass,
double MaxRunningSpeed,
10183 double MaxBrakeRate,
double PowerAtRail, AnsiString ModeStr,
TTrainDataEntry *TrainDataEntryPtr,
int RepeatNumber,
int IncrementalMinutes,
10184 int IncrementalDigits,
int SignallerSpeed,
bool SignallerControl,
TActionEventType &EventType)
10186 LogEvent(AnsiString(Caller) +
",AddTrain," + AnsiString(RearPosition) +
"," + AnsiString(FrontPosition) +
"," + HeadCode +
"," + AnsiString(StartSpeed) +
10187 "," + AnsiString(Mass) +
"," + ModeStr);
10189 "," + HeadCode +
"," + AnsiString(StartSpeed) +
"," + AnsiString(Mass) +
"," + ModeStr);
10191 int RearExitPos = -1;
10193 for(
int x = 0; x < 4; x++)
10200 if(RearExitPos == -1)
10202 throw Exception(
"Error, RearExit == -1 in AddTrain");
10204 bool ReportFlag =
true;
10209 ReportFlag =
false;
10221 if(ModeStr ==
"Timetable")
10227 if(MaxRunningSpeed < 10)
10229 MaxRunningSpeed = 10;
10231 if(SignallerSpeed < 10)
10233 SignallerSpeed = 10;
10235 TTrain *NewTrain =
new TTrain(0, RearPosition, RearExitPos, HeadCode, StartSpeed, Mass, MaxRunningSpeed, MaxBrakeRate, PowerAtRail, TrainMode,
10236 TrainDataEntryPtr, RepeatNumber, IncrementalMinutes, IncrementalDigits, SignallerSpeed);
10243 if(SignallerControl)
10273 if(!SignallerControl)
10288 if(!SignallerControl)
10299 AnsiString Loc =
"";
10316 if(!SignallerControl)
10335 int RouteNumber = -1;
10336 bool SignalsSet =
false;
10343 int RouteStartPosition;
10347 if(FirstPair.first == RouteNumber)
10349 RouteStartPosition = FirstPair.second;
10351 else if(SecondPair.first == RouteNumber)
10353 RouteStartPosition = SecondPair.second;
10357 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 1st of 2 calls to SetAllRearwardsSignals in AddTrain");
10363 else if(RouteNumber > -1)
10383 int LinkedRouteNumber = -1;
10404 int RouteStartPosition;
10408 if(FirstPair.first == RouteNumber)
10410 RouteStartPosition = FirstPair.second;
10412 else if(SecondPair.first == RouteNumber)
10414 RouteStartPosition = SecondPair.second;
10418 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 2nd of 2 calls to SetAllRearwardsSignals in AddTrain");
10424 else if(RouteNumber > -1)
10444 int LinkedRouteNumber = -1;
10465 AnsiString(TrackVectorNumber));
10468 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10477 throw Exception(
"Error, VecPos not set in EntryPos");
10479 if(
TrainVectorAt(2, VecPos).LeadElement == TrackVectorNumber)
10484 else if(
TrainVectorAt(4, VecPos).MidElement == TrackVectorNumber)
10489 else if(
TrainVectorAt(6, VecPos).LagElement == TrackVectorNumber)
10503 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10511 throw Exception(
"Error - No Train identified in TrainVectorAtIdent with ID = " + AnsiString(TrainID));
10521 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10542 return(RepeatTime);
10551 AnsiString RetStr =
"", PartStr =
"";
10559 if((Ptr->Command !=
"") && (Ptr->Command[1] ==
'S'))
10567 if(Ptr->SignallerControl)
10569 RetStr =
"Train under signaller control";
10574 if(Ptr->ArrivalTime == Ptr->DepartureTime)
10585 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime != TDateTime(-1)))
10589 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime == TDateTime(-1)))
10593 else if(Ptr->FormatType ==
PassTime)
10597 else if(Ptr->Command ==
"Fns")
10603 else if(Ptr->Command ==
"F-nshs")
10606 Ptr->NonRepeatingShuttleLinkHeadCode +
" at " + Ptr->LocationName;
10613 else if((Ptr->Command ==
"Fns-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10620 else if((Ptr->Command ==
"Fns-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10623 Ptr->NonRepeatingShuttleLinkHeadCode, +
" at " + Ptr->LocationName;
10626 else if((Ptr->Command ==
"Frh-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10633 else if((Ptr->Command ==
"Frh-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10635 PartStr =
"Terminate at " + Ptr->LocationName;
10637 else if(Ptr->Command ==
"Frh")
10639 PartStr =
"Terminate at " + Ptr->LocationName;
10641 else if(Ptr->Command ==
"Fer")
10643 AnsiString AllowedExits;
10647 else if(Ptr->Command ==
"Fjo")
10650 Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10652 else if(Ptr->Command ==
"jbo")
10655 (50, Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10657 else if(Ptr->Command ==
"fsp")
10662 else if(Ptr->Command ==
"rsp")
10667 else if(Ptr->Command ==
"cdt")
10673 RetStr = RetStr +
'\n' + PartStr;
10681 while(Ptr < TTDEPtr->ActionVector.end() && (Count < 33) && ((Ptr->Command ==
"") || ((Ptr->Command !=
"") && (Ptr->Command[1] !=
'F'))));
10694 + AnsiString(RptNum) +
",ControllerGetNewServiceDepartureInfo," + TDEPtr->
HeadCode);
10695 AnsiString DepTime =
"", EventTime =
"";
10696 bool CDTFlag =
false;
10698 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
10699 AnsiString TowardsLocation =
"";
10702 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
10704 TowardsLocation = AVI->LocationName;
10706 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
10715 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
10721 if(AVI->Command ==
"cdt")
10723 CDTFlag = !CDTFlag;
10726 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
10729 RetStr +=
"\nNew service splits at " + EventTime;
10733 if(AVI->Command ==
"jbo")
10736 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at " + EventTime;
10740 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
10745 if(TowardsLocation !=
"")
10747 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
10751 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
10756 if(TowardsLocation !=
"")
10758 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
10762 RetStr +=
"\nNew service departs at " + DepTime;
10923 ActiveTrackElementNameMapEntry.second = 0;
10929 std::ifstream TTBLFile(FileName, std::ios_base::binary);
10932 if(TTBLFile.is_open())
10934 char *TrainTimetableString =
new char[10000];
10936 bool EndOfFile =
false;
10939 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10941 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10948 delete[] TrainTimetableString;
10952 AnsiString OneLine(TrainTimetableString);
10953 bool FinalCallFalse =
false;
10954 while((Count == 0) && !
ProcessOneTimetableLine(5, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
10958 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10959 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10964 TimetableMessage(GiveMessages,
"Timetable invalid - unable to find a valid start time on its own line");
10966 delete[] TrainTimetableString;
10970 OneLine = AnsiString(TrainTimetableString);
10976 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10978 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10988 OneLine = AnsiString(TrainTimetableString);
10990 if(OneLine.Length() > 9999)
10992 TimetableMessage(GiveMessages,
"Timetable contains a line that is too long - 10,000 or more characters!");
10994 delete[] TrainTimetableString;
10998 bool FinalCallFalse =
false;
10999 if(!
ProcessOneTimetableLine(6, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
11003 delete[] TrainTimetableString;
11007 if(EndOfFile && (Count < 2))
11010 TimetableMessage(GiveMessages,
"Timetable has too few or no relevant entries - must have a start time on its own line and at least one train");
11012 delete[] TrainTimetableString;
11018 delete[] TrainTimetableString;
11023 TimetableMessage(GiveMessages,
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
11034 bool CheckLocationsExistInRailway)
11159 AnsiString((
short)FinalCall) +
"," + AnsiString((
short)CheckLocationsExistInRailway));
11169 if(OneLine[1] !=
'*')
11171 int SCPos = OneLine.Pos(
';');
11182 bool AllCommas =
true;
11184 for(
int x = 1; x < OneLine.Length() + 1; x++)
11186 if(OneLine[x] !=
',')
11191 if(AllCommas || (OneLine ==
""))
11206 AnsiString First =
"", Second =
"", Third =
"", Fourth =
"";
11207 int RearStartOrRepeatMins = 0, FrontStartOrRepeatDigits = 0, NumberOfRepeats = 0;
11208 TDateTime EventTime(0), ArrivalTime(0), DepartureTime(0);
11209 TDateTime StartTime(0);
11211 bool Warning =
false;
11238 AnsiString TrainInfoStr =
"", HeadCode =
"", Description =
"";
11239 int StartSpeed = 0, MaxRunningSpeed = 0, Mass = 0;
11240 double MaxBrakeRate = 0;
11241 double PowerAtRail = 0;
11242 int SignallerSpeed = 0;
11243 if(OneLine[1] ==
'*')
11249 int Pos = OneLine.Pos(
',');
11252 int SubStringLength = 20;
11253 if(OneLine.Length() < 20)
11255 SubStringLength = OneLine.Length();
11257 TimetableMessage(GiveMessages,
"Error in timetable - entry incomplete: see '" + OneLine.SubString(1, SubStringLength) +
"'....");
11261 TrainInfoStr = OneLine.SubString(1, Pos - 1);
11262 if(!
SplitTrainInfo(0, TrainInfoStr, HeadCode, Description, StartSpeed, MaxRunningSpeed, Mass, MaxBrakeRate, PowerAtRail, SignallerSpeed,
11272 TempTrainDataEntry.
HeadCode = HeadCode;
11276 TempTrainDataEntry.
Mass = Mass;
11284 AnsiString NewRemainder = OneLine.SubString(Pos + 1, OneLine.Length() - Pos);
11287 while(NewRemainder[NewRemainder.Length()] ==
',')
11289 if(NewRemainder.Length() > 1)
11291 NewRemainder = NewRemainder.SubString(1, NewRemainder.Length() - 1);
11300 if(NewRemainder ==
"")
11302 TimetableMessage(GiveMessages,
"Error in timetable - no events following train: '" + OneLine +
"'");
11307 int CommaCount = 0;
11308 for(
int x = 1; x < NewRemainder.Length() + 1; x++)
11310 if(NewRemainder[x] ==
',')
11315 if(CommaCount == 0)
11317 if((NewRemainder.SubString(7, 3) !=
"Snt") || (NewRemainder[NewRemainder.Length()] !=
'S'))
11319 int SubStringLength = 20;
11320 if(OneLine.Length() < 20)
11322 SubStringLength = OneLine.Length();
11325 "Error in timetable - must have at least a start and a finish event for a train that is not started under signaller control - see line beginning: '" +
11326 OneLine.SubString(1, SubStringLength) +
"'....");
11331 AnsiString OneEntry =
"";
11336 bool FinishFlag =
false;
11337 for(
int x = 0; x < CommaCount + 1; x++)
11339 if((CommaCount == 0) || (x < CommaCount))
11344 if(CommaCount == 0)
11346 OneEntry = NewRemainder;
11351 Pos = NewRemainder.Pos(
',');
11352 OneEntry = NewRemainder.SubString(1, Pos - 1);
11353 NewRemainder = NewRemainder.SubString(Pos + 1, NewRemainder.Length() - Pos);
11359 RearStartOrRepeatMins = 0;
11360 FrontStartOrRepeatDigits = 0;
11361 NumberOfRepeats = 0;
11362 if(!
SplitEntry(0, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11363 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11365 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
11370 if(Warning && (Second ==
"Frh"))
11372 TimetableMessage(GiveMessages,
"Error in line - '" + OneEntry +
"': warnings cannot be given for 'Frh' events");
11376 if(Warning && (Second ==
"Fjo"))
11379 "': warnings cannot be given for 'Fjo' events, for a train join warning add a 'W' prefix to the 'jbo' event");
11385 if(SequenceType !=
Start)
11387 TimetableMessage(GiveMessages,
"Error in timetable - First event not a start event: '" + OneEntry +
"'");
11391 if((Second ==
"Snt") && (Fourth ==
'S') && (NewRemainder !=
""))
11393 if(NewRemainder[1] !=
'R')
11396 "Error in timetable - the only event that can follow a train created under signaller control is a repeat, see '" +
11402 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11406 if((HeadCode ==
"") || (Description ==
"") || (MaxRunningSpeed == 0) || (Mass == 0) || (MaxBrakeRate == 0))
11409 TimetableMessage(GiveMessages,
"Error in timetable - train information incomplete before 'Snt' or 'Snt-sh' start event: '" +
11415 if((Second ==
"Sfs") || (Second ==
"Sns") || (Second ==
"Sns-sh") || (Second ==
"Sns-fsh"))
11420 TimetableMessage(GiveMessages,
"Error in timetable - headcode missing before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11425 if((StartSpeed != 0) || (MaxRunningSpeed != 0) || (Mass != 0) || (MaxBrakeRate != 0) || (PowerAtRail != 0))
11428 "Error in timetable - information additional to a headcode & optional description given before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11435 if(SequenceType ==
Finish)
11444 TDateTime TempTime;
11450 ActionVectorEntry.
Warning = Warning;
11466 ActionVectorEntry.
Command = Second;
11481 else if(FormatType ==
TimeCmd)
11487 ActionVectorEntry.
Command = Second;
11495 ActionVectorEntry.
Command = Second;
11496 ActionVectorEntry.
ExitList = ExitList;
11504 ActionVectorEntry.
Command = Second;
11518 ActionVectorEntry.
Command = Second;
11529 ActionVectorEntry.
Command = Second;
11539 ActionVectorEntry.
Command = Second;
11548 ActionVectorEntry.
Command = Second;
11557 ActionVectorEntry.
Command = Second;
11563 ActionVectorEntry.
Command = Second;
11565 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11570 OneEntry = NewRemainder;
11575 RearStartOrRepeatMins = 0;
11576 FrontStartOrRepeatDigits = 0;
11577 NumberOfRepeats = 0;
11578 if((FinishFlag) && (OneEntry[1] !=
'R'))
11581 TimetableMessage(GiveMessages,
"Error in timetable - Last event = '" + OneEntry +
"'. An earlier finish event has been found with something other than a repeat following it - only a repeat can follow a finish event.");
11585 if(OneEntry[1] !=
'R')
11587 if(!
SplitEntry(1, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11588 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11590 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
11594 if(SequenceType !=
Finish)
11596 TimetableMessage(GiveMessages,
"Error in timetable - last event should be a finish: '" + OneEntry +
"'");
11603 TDateTime TempTime;
11609 ActionVectorEntry.
Warning = Warning;
11616 ActionVectorEntry.
Command = Second;
11624 ActionVectorEntry.
Command = Second;
11633 ActionVectorEntry.
Command = Second;
11642 ActionVectorEntry.
Command = Second;
11652 ActionVectorEntry.
Command = Second;
11653 ActionVectorEntry.
ExitList = ExitList;
11657 ActionVectorEntry.
Command = Second;
11659 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11664 if(!
SplitRepeat(0, OneEntry, RearStartOrRepeatMins, FrontStartOrRepeatDigits, NumberOfRepeats, GiveMessages))
11680 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11699 if((HeadCode[HeadCode.Length() - 1] <
'0') || (HeadCode[HeadCode.Length() - 1] >
'9'))
11704 if((HeadCode[HeadCode.Length()] <
'0') || (HeadCode[HeadCode.Length()] >
'9'))
11719 if(TimeStr.Length() < 5)
11724 if((TimeStr[1] <
'0') || (TimeStr[1] >
'9'))
11729 if((TimeStr[2] <
'0') || (TimeStr[2] >
'9'))
11734 if(TimeStr[3] !=
':')
11739 if((TimeStr[4] <
'0') || (TimeStr[4] >
'5'))
11744 if((TimeStr[5] <
'0') || (TimeStr[5] >
'9'))
11749 while(TimeStr.Length() > 5)
11751 TimeStr = TimeStr.SubString(1, TimeStr.Length() - 1);
11753 double WholeHours = (AnsiString(TimeStr[1]) + AnsiString(TimeStr[2])).ToDouble();
11754 double FracHour = ((AnsiString(TimeStr[4]) + AnsiString(TimeStr[5])).ToDouble()) / 60.0;
11756 if((WholeHours + FracHour) >= 95.98334)
11761 Time = TDateTime((WholeHours + FracHour) / 24);
11768 bool TTrainController::SplitEntry(
int Caller, AnsiString OneEntry,
bool GiveMessages,
bool CheckLocationsExistInRailway, AnsiString &First, AnsiString &Second,
11769 AnsiString &Third, AnsiString &Fourth,
int &RearStartOrRepeatMins,
int &FrontStartOrRepeatDigits,
TTimetableFormatType &FormatType,
11778 TDateTime TempTime;
11780 if(OneEntry.Length() > 0)
11782 if(OneEntry[1] ==
'W')
11785 OneEntry = OneEntry.SubString(2, OneEntry.Length() - 1);
11789 if(OneEntry ==
"Frh")
11799 if(OneEntry.Length() < 7)
11804 int Pos = OneEntry.Pos(
';');
11812 First = OneEntry.SubString(1, 5);
11818 AnsiString Remainder = OneEntry.SubString(Pos + 1, OneEntry.Length() - Pos);
11820 if((Remainder[1] >=
'0') && (Remainder[1] <=
'9'))
11823 if(Remainder.Length() < 7)
11828 Pos = Remainder.Pos(
';');
11835 Second = Remainder.SubString(1, 5);
11841 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11854 Pos = Remainder.Pos(
';');
11857 Second = Remainder;
11858 if(Second ==
"cdt")
11883 if((Pos != 4) && (Pos != 7) && (Pos != 8))
11889 Second = Remainder.SubString(1, Pos - 1);
11891 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11893 Pos = Remainder.Pos(
';');
11900 Third = Remainder.SubString(1, Pos - 1);
11901 Fourth = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11903 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11906 int SpacePos = Third.Pos(
' ');
11912 AnsiString RearStartStr = Third.SubString(1, SpacePos - 1);
11913 AnsiString FrontStartStr = Third.SubString(SpacePos + 1, Third.Length() - SpacePos);
11915 if(CheckLocationsExistInRailway)
11925 if(Second ==
"Snt")
11928 SequenceType =
Start;
11937 SequenceType =
Start;
11948 if(Second ==
"Sns-sh")
11952 SequenceType =
Start;
11967 if(Second ==
"F-nshs")
11981 if(Second ==
"Sns-fsh")
11985 SequenceType =
Start;
11995 if(Second ==
"Fns-sh")
12015 if(Second ==
"pas")
12030 if(Second ==
"Fer")
12037 if(CheckLocationsExistInRailway)
12049 if((Second !=
"Fns") && (Second !=
"Fjo") && (Second !=
"jbo") && (Second !=
"fsp") && (Second !=
"rsp") && (Second !=
"Sfs") && (Second !=
"Sns") &&
12050 (Second !=
"Frh-sh"))
12062 if(Second ==
"Frh-sh")
12070 if((Second ==
"Fns") || (Second ==
"Fjo") || (Second ==
"Frh-sh"))
12074 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp"))
12078 if((Second ==
"Sfs") || (Second ==
"Sns"))
12080 SequenceType =
Start;
12098 if((LocStr[1] >=
'0') && (LocStr[1] <=
'9'))
12103 for(
int x = 1; x < LocStr.Length() + 1; x++)
12105 if(LocStr[x] <
' ')
12110 if(LocStr[x] >
'z')
12117 if(CheckLocationsExistInRailway)
12122 "' appears in the timetable but is not a valid name. To be valid the name must be a stopping location and apply to one or more platforms " +
12123 "(not concourses on their own), or to track at a blue non-station named location. BUT NOTE THAT trains can't stop at continuations so a name " +
12124 "that includes a continuation will not be valid.");
12142 if((HeadCode.Length() < 4) || (HeadCode.Length() > 8))
12145 "', length must be between 4 and 8 characters, and last 4 must be a legitimate headcode. This error can also be caused by omitting a service reference after Sns, Snt-sh, Sns-sh, Fns, Fns-sh or Frh-sh");
12150 for(
int x = 1; x < (HeadCode.Length() + 1); x++)
12152 if((HeadCode[x] <
' ') || (HeadCode[x] >
'~'))
12154 TimetableMessage(GiveMessages,
"Non-printable character in headcode '" + HeadCode +
"'");
12160 for(
int x = 3; x >= 0; x--)
12162 if(((HeadCode[HeadCode.Length() - x] <
'A') || (HeadCode[HeadCode.Length() - x] >
'Z')) && ((HeadCode[HeadCode.Length() - x] <
'a') ||
12163 (HeadCode[HeadCode.Length() - x] >
'z')) && ((HeadCode[HeadCode.Length() - x] <
'0') || (HeadCode[HeadCode.Length() - x] >
'9')))
12165 TimetableMessage(GiveMessages,
"Headcode error in '" + HeadCode +
"', headcode must consist of letters and digits only");
12181 AnsiString CurrentID =
"";
12183 if(IDSet.Length() == 0)
12185 TimetableMessage(GiveMessages,
"Must have at least one exit element ID following 'Fer'");
12189 for(
int x = 1; x <= IDSet.Length(); x++)
12192 if(((C <
'0') || (C >
'9')) && (C !=
' ') && (C !=
'N') && (C !=
'-'))
12194 TimetableMessage(GiveMessages,
"Illegal character in the set of element IDs following 'Fer' in '" + IDSet +
"'");
12216 int Pos = IDSet.Pos(
' ');
12227 CurrentID = IDSet.SubString(1, Pos - 1);
12228 IDSet = IDSet.SubString(Pos + 1, IDSet.Length() - Pos);
12240 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' is not an exit");
12247 if(!ExitList.empty())
12249 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
12251 if(*ELIT == VecPos)
12253 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' duplicates an earlier element");
12260 ExitList.push_back(VecPos);
12270 Pos = IDSet.Pos(
' ');
12277 int &Mass,
double &MaxBrakeRate,
double &PowerAtRail,
int &SignallerSpeed,
bool GiveMessages)
12284 AnsiString Remainder =
"";
12285 int SemiColonCount = 0;
12287 for(
int x = 1; x < TrainInfoStr.Length() + 1; x++)
12289 if(TrainInfoStr[x] ==
';')
12294 if((SemiColonCount != 6) && (SemiColonCount != 7) && (SemiColonCount != 1) && (SemiColonCount != 0))
12296 TimetableMessage(GiveMessages,
"Error in train information in '" + TrainInfoStr +
12297 "'. Should be headcode + optional description for a continuing service;" +
12298 " or headcode, description, start speed, max running speed, mass, brake force, power (and optional signaller max. speed) for a new service");
12302 if(SemiColonCount == 0)
12304 HeadCode = TrainInfoStr;
12313 if(SemiColonCount == 1)
12315 Pos = TrainInfoStr.Pos(
';');
12316 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12317 Description = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12323 if(Description ==
"")
12325 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
12329 if(Description.Length() > 60)
12331 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
12335 for(
int x = 1; x < Description.Length() + 1; x++)
12337 if((Description[x] <
' ') || (Description[x] >
'~'))
12339 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
12348 Pos = TrainInfoStr.Pos(
';');
12349 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12350 Remainder = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12356 Pos = Remainder.Pos(
';');
12357 Description = Remainder.SubString(1, Pos - 1);
12358 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12359 if(Description ==
"")
12361 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
12365 if(Description.Length() > 60)
12367 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
12371 for(
int x = 1; x < Description.Length() + 1; x++)
12373 if((Description[x] <
' ') || (Description[x] > 126))
12375 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
12380 Pos = Remainder.Pos(
';');
12381 AnsiString StartSpeedStr = Remainder.SubString(1, Pos - 1);
12383 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12384 if(StartSpeedStr ==
"")
12386 TimetableMessage(GiveMessages,
"Train starting speed missing in '" + TrainInfoStr +
"'");
12390 for(
int x = 1; x < StartSpeedStr.Length() + 1; x++)
12392 if((StartSpeedStr[x] <
'0') || (StartSpeedStr[x] >
'9'))
12394 TimetableMessage(GiveMessages,
"Train start speed contains invalid characters in '" + TrainInfoStr +
"'");
12399 StartSpeed = StartSpeedStr.ToInt();
12405 TimetableMessage(GiveMessages,
"Train starting speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12409 Pos = Remainder.Pos(
';');
12410 AnsiString MaxRunningSpeedStr = Remainder.SubString(1, Pos - 1);
12412 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12413 if(MaxRunningSpeedStr ==
"")
12415 TimetableMessage(GiveMessages,
"Train maximum running speed missing in '" + TrainInfoStr +
"'");
12419 for(
int x = 1; x < MaxRunningSpeedStr.Length() + 1; x++)
12421 if((MaxRunningSpeedStr[x] <
'0') || (MaxRunningSpeedStr[x] >
'9'))
12423 TimetableMessage(GiveMessages,
"Train maximum running speed contains invalid characters in '" + TrainInfoStr +
"'");
12428 MaxRunningSpeed = MaxRunningSpeedStr.ToInt();
12434 TimetableMessage(GiveMessages,
"Train maximum running speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12438 if(MaxRunningSpeed < 10)
12441 MaxRunningSpeed = 10;
12444 TimetableMessage(GiveMessages,
"Train maximum running speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
12448 Pos = Remainder.Pos(
';');
12449 AnsiString MassStr = Remainder.SubString(1, Pos - 1);
12451 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12454 TimetableMessage(GiveMessages,
"Train mass missing in '" + TrainInfoStr +
"'");
12458 for(
int x = 1; x < MassStr.Length() + 1; x++)
12460 if((MassStr[x] <
'0') || (MassStr[x] >
'9'))
12462 TimetableMessage(GiveMessages,
"Train mass contains invalid characters in '" + TrainInfoStr +
"'");
12467 Mass = MassStr.ToInt() * 1000;
12473 TimetableMessage(GiveMessages,
"Train mass > 10,000 tonnes in '" + TrainInfoStr +
"'. Setting it to 10,000 tonnes");
12479 TimetableMessage(GiveMessages,
"Train mass zero in '" + TrainInfoStr +
"'");
12483 Pos = Remainder.Pos(
';');
12484 AnsiString MaxBrakeForceStr = Remainder.SubString(1, Pos - 1);
12486 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12487 if(MaxBrakeForceStr ==
"")
12489 TimetableMessage(GiveMessages,
"Train braking force missing in '" + TrainInfoStr +
"'");
12493 for(
int x = 1; x < (MaxBrakeForceStr.Length() + 1); x++)
12495 if((MaxBrakeForceStr[x] !=
'.') && ((MaxBrakeForceStr[x] <
'0') || (MaxBrakeForceStr[x] >
'9')))
12497 TimetableMessage(GiveMessages,
"Train braking force contains invalid characters in '" + TrainInfoStr +
"'");
12502 double MaxBrakeForce = MaxBrakeForceStr.ToDouble() * 1000;
12505 if((MaxBrakeForce / Mass) > 1)
12507 MaxBrakeForce = Mass;
12510 TimetableMessage(GiveMessages,
"Train braking force too high in '" + TrainInfoStr +
"'. Setting it to the same as the train mass");
12514 if((MaxBrakeForce / Mass) < 0.01)
12516 MaxBrakeForce = Mass * 0.01;
12519 TimetableMessage(GiveMessages,
"Train braking force too low in '" + TrainInfoStr +
"'. Setting it to 1% of the train mass");
12524 MaxBrakeRate = MaxBrakeForce / Mass * 9.81;
12526 AnsiString GrossPowerStr =
"", SignallerSpeedStr =
"";
12528 if(SemiColonCount == 6)
12530 GrossPowerStr = Remainder;
12531 SignallerSpeedStr =
"30";
12535 Pos = Remainder.Pos(
';');
12536 GrossPowerStr = Remainder.SubString(1, Pos - 1);
12537 SignallerSpeedStr = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12540 if(GrossPowerStr ==
"")
12542 TimetableMessage(GiveMessages,
"Train power missing in '" + TrainInfoStr +
"'");
12546 for(
int x = 1; x < GrossPowerStr.Length() + 1; x++)
12548 if((GrossPowerStr[x] <
'0') || (GrossPowerStr[x] >
'9'))
12550 TimetableMessage(GiveMessages,
"Train power contains invalid characters in '" + TrainInfoStr +
"'");
12556 double GrossPower = GrossPowerStr.ToInt() * 1000;
12563 TimetableMessage(GiveMessages,
"Train power > 100,000kW in '" + TrainInfoStr +
"'. Setting it to 100,000kW");
12567 else if(GrossPower == 0)
12572 else if((GrossPower > 0) && (GrossPower < 10000))
12575 GrossPower = 10000;
12577 PowerAtRail = GrossPower * 0.8;
12581 if(SignallerSpeedStr ==
"")
12583 TimetableMessage(GiveMessages,
"Signaller speed not set in '" + TrainInfoStr +
"', either set a value or remove the extra semicolon");
12587 for(
int x = 1; x < SignallerSpeedStr.Length() + 1; x++)
12589 if((SignallerSpeedStr[x] <
'0') || (SignallerSpeedStr[x] >
'9'))
12591 TimetableMessage(GiveMessages,
"Signaller speed contains invalid characters in '" + TrainInfoStr +
"'");
12596 SignallerSpeed = SignallerSpeedStr.ToInt();
12602 TimetableMessage(GiveMessages,
"Signaller speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12606 if(SignallerSpeed < 10)
12609 SignallerSpeed = 10;
12612 TimetableMessage(GiveMessages,
"Signaller speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
12630 if(OneEntry.Length() < 7)
12632 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12636 int SemiColonCount = 0;
12638 for(
int x = 1; x < OneEntry.Length() + 1; x++)
12640 if(OneEntry[x] ==
';')
12645 if(SemiColonCount != 3)
12647 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12651 if((OneEntry[1] !=
'R') || (OneEntry[2] !=
';'))
12653 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12657 AnsiString Remainder = OneEntry.SubString(3, OneEntry.Length() - 2);
12662 Pos = Remainder.Pos(
';');
12663 AnsiString MinutesStr = Remainder.SubString(1, Pos - 1);
12665 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12666 if(MinutesStr ==
"")
12668 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute increment segment missing");
12672 if(MinutesStr.Length() > 3)
12675 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute value too high, maximum value is 999");
12679 for(
int x = 1; x < MinutesStr.Length() + 1; x++)
12681 if((MinutesStr[x] <
'0') || (MinutesStr[x] >
'9'))
12683 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in minute increment segment");
12688 RearStartOrRepeatMins = MinutesStr.ToInt();
12689 if(RearStartOrRepeatMins == 0)
12691 TimetableMessage(GiveMessages,
"Repeat minute increment is zero in: '" + OneEntry +
"' - can't have a zero value");
12695 Pos = Remainder.Pos(
';');
12696 AnsiString DigitsStr = Remainder.SubString(1, Pos - 1);
12698 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12699 if(DigitsStr ==
"")
12701 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - headcode increment segment missing");
12705 for(
int x = 1; x < DigitsStr.Length() + 1; x++)
12707 if((DigitsStr[x] <
'0') || (DigitsStr[x] >
'9'))
12709 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in headcode increment segment");
12714 if(DigitsStr.Length() > 2)
12716 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - maximum number of digits for headcode increment is 2");
12720 FrontStartOrRepeatDigits = DigitsStr.ToInt();
12734 "' - a repeating service with incrementing digits must have digits as its last two headcode characters");
12738 AnsiString NumberStr = Remainder;
12740 if(NumberStr ==
"")
12742 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - number of repeats missing");
12746 if(NumberStr.Length() > 4)
12749 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - repeat value too high, no timetabled event can exceed 95 hours & 59 minutes");
12753 for(
int x = 1; x < NumberStr.Length() + 1; x++)
12755 if((NumberStr[x] <
'0') || (NumberStr[x] >
'9'))
12758 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in number of repeats");
12763 NumberOfRepeats = NumberStr.ToInt();
12764 if(NumberOfRepeats == 0)
12766 TimetableMessage(GiveMessages,
"Number of repeats is zero in: '" + OneEntry +
"' - if no repeats are needed the repeat should be omitted");
12938 SecondPassMessage(GiveMessages,
"Error in timetable - there appear to be no train services in the timetable, it must contain at least one");
12957 TwoLocationFlag =
false;
12963 SecondPassMessage(GiveMessages,
"Error in timetable - the following service has no listed events, there must be at least one: " + TDEntry.
HeadCode);
12977 SecondPassMessage(GiveMessages,
"Error in timetable - service must have a start event and at least one other for: " + TDEntry.
HeadCode);
12993 "Error in timetable - a signaller control service can have no more than one item (a repeat) after the start event, see: " +
13005 "Error in timetable - a signaller control service cannot have any other than a repeat after the start event, see: " + TDEntry.
HeadCode);
13032 SecondPassMessage(GiveMessages,
"Error in timetable - finish events Fns-sh and Frh-sh not permitted immediately after an Snt entry for: " +
13043 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13048 SecondPassMessage(GiveMessages,
"Error in timetable - a start event is present that is not the first event for: " + TDEntry.
HeadCode);
13058 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13063 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat is present that is not the last item for: " + TDEntry.
HeadCode);
13073 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13084 SecondPassMessage(GiveMessages,
"Error in timetable - the last item must be either a finish event or a repeat for: " + TDEntry.
HeadCode);
13094 SecondPassMessage(GiveMessages,
"Error in timetable - the last event before the repeat must be a finish for: " + TDEntry.
HeadCode);
13106 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13113 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event must be either the last or last but one for: " + TDEntry.
HeadCode);
13122 SecondPassMessage(GiveMessages,
"Error in timetable - the only event that can follow a finish event is a repeat for: " +
13142 if((AVEntry0.
Command ==
"Snt") || (AVEntry0.
Command ==
"Snt-sh"))
13144 AnsiString LocationName =
"";
13160 SecondPassMessage(GiveMessages,
"Error in timetable - stopped 'Snt' or 'Snt-sh' followed by an illegal event for: " +
13161 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
13170 SecondPassMessage(GiveMessages,
"Error in timetable - 'Snt' or 'Snt-sh' event at stop location but start speed not zero for: " +
13179 if(AVEntry0.
Command ==
"Snt-sh")
13193 SecondPassMessage(GiveMessages,
"Error in timetable - unlocated 'Snt' not followed by 'Fer', 'pas' or an arrival for: " +
13209 SecondPassMessage(GiveMessages,
"Error in timetable - 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' followed by an illegal event for: " +
13210 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
13221 bool FoundFlag =
false;
13227 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13239 SecondPassMessage(GiveMessages,
"Error in timetable - no location departure following an 'Sfs', 'Sns', 'Sns-sh'or 'Sns-fsh' event for: " +
13252 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13261 ": an event should have had a location name associated with it but it could not be found");
13267 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
13289 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13299 SecondPassMessage(GiveMessages,
"Error in timetable - only a repeat can follow a finish entry for: " + TDEntry.
HeadCode);
13306 if(AVEntry.
Command ==
"F-nshs")
13311 SecondPassMessage(GiveMessages,
"Error in timetable - F-nshs (shuttle link) must be the last event for: " + TDEntry.
HeadCode);
13339 SecondPassMessage(GiveMessages,
"Error in timetable - a jbo event is followed by an illegal event for: " + TDEntry.
HeadCode +
13340 ". The event isn't valid for a stationary train.");
13350 SecondPassMessage(GiveMessages,
"Error in timetable - a train split can't be the last event for: " + TDEntry.
HeadCode);
13358 SecondPassMessage(GiveMessages,
"Error in timetable - a train split is followed by an illegal event for: " + TDEntry.
HeadCode +
13359 ". The event isn't valid for a stationary train.");
13377 SecondPassMessage(GiveMessages,
"Error in timetable - a 'cdt' is followed by an illegal event for: " + TDEntry.
HeadCode +
13378 ". The event isn't valid for a stationary train.");
13388 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure can't be the last event for: " + TDEntry.
HeadCode);
13396 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure is followed by an illegal event for: " +
13397 TDEntry.
HeadCode +
". The event isn't valid for a moving train.");
13415 SecondPassMessage(GiveMessages,
"Error in timetable - a pass time is followed by an illegal event for: " + TDEntry.
HeadCode +
13416 ". The event isn't valid for a moving train.");
13438 bool LastEntryIsAnArrival =
false;
13445 LastEntryIsAnArrival =
false;
13446 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13453 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
13455 if(LastEntryIsAnArrival)
13459 LastEntryIsAnArrival =
false;
13465 LastEntryIsAnArrival =
true;
13472 LastEntryIsAnArrival =
true;
13473 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13480 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
13482 if(LastEntryIsAnArrival)
13486 LastEntryIsAnArrival =
false;
13492 LastEntryIsAnArrival =
true;
13502 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13510 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival can't be the last event for: " + TDEntry.
HeadCode);
13518 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival is followed by an illegal event for: " + TDEntry.
HeadCode +
13519 ". The event isn't valid for a stationary train.");
13530 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure can't be the last event for: " + TDEntry.
HeadCode);
13538 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure is followed by an illegal event for: " + TDEntry.
HeadCode +
13539 ". The event isn't valid for a moving train.");
13553 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13560 throw Exception(
"Timetable error, TimeLoc entry has EventTime not -1 for " + TDEntry.
HeadCode);
13564 throw Exception(
"Timetable error, TimeLoc entry has neither arrival nor departure time set for " + TDEntry.
HeadCode);
13571 throw Exception(
"Timetable error, TimeTimeLoc entry has EventTime not -1 for " + TDEntry.
HeadCode);
13575 throw Exception(
"Timetable error, TimeTimeLoc entry has either arrival or departure time not set for " + TDEntry.
HeadCode);
13584 throw Exception(
"Timetable error, Cmd or PassTime entry has EventTime not set for " + TDEntry.
HeadCode);
13588 throw Exception(
"Timetable error, Cmd or PassTime entry has either arrival or departure time set for " + TDEntry.
HeadCode);
13595 throw Exception(
"Timetable error, Repeat entry has a time set for " + TDEntry.
HeadCode);
13606 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13621 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has a later arrival than departure time for: " +
13629 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has too early an arrival time for: " +
13644 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
13656 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
13668 SecondPassMessage(GiveMessages,
"Error in timetable - a train event has a time that is set too early for: " + TDEntry.
HeadCode +
13669 ", may be before timetable start time");
13680 AnsiString LastLocationName =
"";
13684 bool LastEntryIsAnArrival =
false;
13689 LastEntryIsAnArrival =
false;
13690 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
13691 if(LastLocationName !=
"")
13693 throw Exception(
"Timetable error, moving Snt entry has LocationName set for " + TDEntry.
HeadCode);
13695 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size();
13708 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
13720 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
13733 TwoLocationFlag =
true;
13738 LastEntryIsAnArrival =
false;
13742 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
13745 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
13750 else if(!LastEntryIsAnArrival && (AVEntry.
LocationName == LastLocationName))
13753 "Error in timetable - a location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode);
13759 LastEntryIsAnArrival = !LastEntryIsAnArrival;
13765 LastEntryIsAnArrival =
true;
13766 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
13767 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13779 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
13791 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
13804 TwoLocationFlag =
true;
13809 LastEntryIsAnArrival =
false;
13813 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
13816 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
13824 "A location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode +
". Please correct if this is an error.\n\nThis warning will not be shown again.");
13831 LastEntryIsAnArrival = !LastEntryIsAnArrival;
13839 AnsiString LocationNameToBeChecked =
"";
13844 unsigned int y = 0;
13858 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
13859 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
13877 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
13886 TwoLocationFlag =
true;
13897 if(TwoLocationFlag)
13907 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13912 throw Exception(
"Error, non- 'Snt', 'Fer' or Repeat entry doesn't have a location name set for " + TDEntry.
HeadCode);
13914 AnsiString LocName =
"";
13920 throw Exception(
"Error, 'Snt' entry at a stop location doesn't have a location name set for " + TDEntry.
HeadCode);
13927 throw Exception(
"Error, 'Snt' unlocated entry has a location name set for " + TDEntry.
HeadCode);
13950 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13975 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13997 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14019 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14038 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14041 if((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh"))
14056 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14061 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has FormatType unset for: " + TDEntry.
HeadCode);
14065 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has SequenceType unset for: " + TDEntry.
HeadCode);
14069 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has LocationType unset for: " + TDEntry.
HeadCode);
14073 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has ShuttleLinkType unset for: " + TDEntry.
HeadCode);
14112 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14114 AnsiString LocName =
TrainDataVector.at(x).ActionVector.at(y).LocationName;
14120 SecondPassMessage(GiveMessages,
"Error in timetable - continuation names (" + LocName +
") must not be included, see service " + HC);
14133 int IncMinutes = 0;
14143 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14149 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat time exceeds 95h 59m, see service " + HC);
14155 if((
double)
TrainDataVector.at(x).ActionVector.at(y).ArrivalTime > -1)
14160 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat entry time exceeds 95h 59m, see service " + HC);
14166 if((
double)
TrainDataVector.at(x).ActionVector.at(y).DepartureTime > -1)
14171 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat entry time exceeds 95h 59m, see service " + HC);
14184 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14210 (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"F-nshs"));
14218 if(HeadCode.Length() > 4)
14220 HeadCode = HeadCode.SubString(HeadCode.Length() - 3, 4);
14231 int ForwardCount = 0;
14232 int ReverseCount = 0;
14234 if(MainHeadCode == SecondHeadCode)
14236 SecondPassMessage(GiveMessages,
"Error in timetable - Service " + MainHeadCode +
" has an event that references itself");
14245 if(TDEntry.
HeadCode == MainHeadCode)
14247 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14262 if(ForwardCount == 0)
14265 throw Exception(
"Error, ForwardCount == 0 in CheckForDuplicateCrossReferences after called with found values");
14267 if(ForwardCount > 2)
14270 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + SecondHeadCode +
" from a train whose headcode is " +
14271 MainHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
14280 if(TDEntry.
HeadCode == SecondHeadCode)
14282 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14297 if(ReverseCount == 0)
14299 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + SecondHeadCode);
14304 if(ReverseCount > 2)
14307 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + MainHeadCode +
" from a train whose headcode is " +
14308 SecondHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
14313 if(ForwardCount != ReverseCount)
14315 SecondPassMessage(GiveMessages,
"Error in timetable - " + MainHeadCode +
" has a different number of references to " + SecondHeadCode +
14316 " than the other way round");
14347 int ForwardCount = 0;
14348 int ReverseCount = 0;
14349 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
14358 if(TDEntry.
HeadCode == MainHeadCode)
14360 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14363 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
14368 ForwardEntryPtr = &AVEntry;
14370 ForwardTDVectorNumber = x;
14373 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") ||
14374 (AVEntry.
Command ==
"Frh-sh")))
14379 ForwardEntryPtr = &AVEntry;
14381 ForwardTDVectorNumber = x;
14387 if(ForwardCount == 0)
14390 throw Exception(
"Error, ForwardCount == 0 in CheckCrossReferencesAndSetData after called with found values");
14392 if(ForwardCount > 1)
14394 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + OtherHeadCode +
" from a train whose headcode is " +
14404 if(TDEntry.
HeadCode == OtherHeadCode)
14406 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14409 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
14415 ReverseEntryPtr = &AVEntry;
14416 ReverseTDVectorNumber = x;
14419 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"Frh-sh")))
14425 ReverseEntryPtr = &AVEntry;
14426 ReverseTDVectorNumber = x;
14433 if(ReverseCount == 0)
14435 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + OtherHeadCode);
14440 if(ReverseCount > 1)
14442 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
14449 bool ForwardShuttleStart = ((ForwardEntryPtr->Command ==
"Sns-sh") || (ForwardEntryPtr->Command ==
"Snt-sh"));
14450 bool ForwardShuttleFinish = ((ForwardEntryPtr->Command ==
"Fns-sh") || (ForwardEntryPtr->Command ==
"Frh-sh"));
14451 bool ReverseShuttleStart = ((ReverseEntryPtr->
Command ==
"Sns-sh") || (ReverseEntryPtr->
Command ==
"Snt-sh"));
14452 bool ReverseShuttleFinish = ((ReverseEntryPtr->
Command ==
"Fns-sh") || (ReverseEntryPtr->
Command ==
"Frh-sh"));
14456 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat");
14463 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + OtherHeadCode +
" does not have a repeat");
14468 if(ForwardEntryPtr->LocationName ==
"")
14470 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
14471 ". One or other service does not have a location set");
14478 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
14479 ". One or other service does not have a location set");
14484 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
14486 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
14487 " is at a different location to the referencing train " + MainHeadCode);
14495 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
14497 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
14498 " has a different event time to the referencing train " + MainHeadCode);
14506 if(ForwardShuttleStart && ReverseShuttleFinish)
14511 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle service " + MainHeadCode +
14512 " first repeat restart time not consistent with finish service " + OtherHeadCode);
14518 if((ReverseEntryPtr->
Command ==
"Sfs") || (ReverseEntryPtr->
Command ==
"Sns"))
14521 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
14523 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' or 'Sns' event (" + OtherHeadCode +
14524 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
14530 if(ReverseEntryPtr->
Command ==
"Fjo")
14533 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
14535 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fjo' event (" + OtherHeadCode +
14536 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
14542 if(ReverseEntryPtr->
Command ==
"Fns")
14545 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
14547 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' event (" + OtherHeadCode +
14548 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
14554 if(ForwardEntryPtr->Command ==
"Sfs")
14556 if((ReverseEntryPtr->
Command !=
"fsp") && (ReverseEntryPtr->
Command !=
"rsp"))
14559 "Error in timetable - unable to find a corresponding split train event for the train that starts from a split whose headcode is " +
14566 if((ForwardEntryPtr->Command ==
"fsp") || (ForwardEntryPtr->Command ==
"rsp"))
14568 if(ReverseEntryPtr->
Command !=
"Sfs")
14570 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sfs' event for the train split whose headcode is " +
14580 SecondPassMessage(GiveMessages,
"Error in timetable - can't find timetabled location '" + ForwardEntryPtr->LocationName +
"' in railway - perhaps there are concourses without platforms?");
14587 SecondPassMessage(GiveMessages,
"Error in timetable - can't find any named location elements at '" + ForwardEntryPtr->LocationName +
"' - perhaps there are concourses without platforms?");
14594 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
14599 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
14610 if(ForwardEntryPtr->Command ==
"Sns")
14612 if(ReverseEntryPtr->
Command !=
"Fns")
14614 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fns' event for the 'Sns' train whose headcode is " +
14615 MainHeadCode +
" and is formed from a service with headcode " + OtherHeadCode);
14621 if(ForwardEntryPtr->Command ==
"Fns")
14623 if(ReverseEntryPtr->
Command !=
"Sns")
14625 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns' event for the train whose headcode is " + MainHeadCode +
14626 " and forms a new service with headcode " + OtherHeadCode);
14633 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
14644 if(ForwardEntryPtr->Command ==
"jbo")
14646 if(ReverseEntryPtr->
Command !=
"Fjo")
14648 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fjo' event for the train whose headcode is " + MainHeadCode +
14649 " and is joined by a train with headcode " + OtherHeadCode);
14655 if(ForwardEntryPtr->Command ==
"Fjo")
14657 if(ReverseEntryPtr->
Command !=
"jbo")
14659 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'jbo' event for the train whose headcode is " + MainHeadCode +
14660 " and joins a train with headcode " + OtherHeadCode);
14667 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
14677 if(ForwardShuttleStart)
14680 if(!ReverseShuttleFinish)
14683 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + MainHeadCode +
14684 " from train whose headcode is " + OtherHeadCode +
", has to be Fns-sh, Frh-sh");
14690 if(ReverseShuttleStart)
14693 if(!ForwardShuttleFinish)
14696 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + OtherHeadCode +
14697 " from train whose headcode is " + MainHeadCode +
", has to be Fns-sh, Frh-sh");
14704 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
14716 bool MainRepeat =
false, OtherRepeat =
false;
14726 OtherRepeat =
true;
14729 if((MainRepeat && !OtherRepeat) || (!MainRepeat && OtherRepeat))
14731 SecondPassMessage(GiveMessages,
"Error in timetable - only one repeat is provided for the train whose headcode is " + MainHeadCode +
14732 " and the associated train with headcode " + OtherHeadCode);
14737 if(MainRepeat && OtherRepeat)
14743 SecondPassMessage(GiveMessages,
"Error in timetable - repeat items don't correspond for the train whose headcode is " + MainHeadCode +
14744 " and the associated train with headcode " + OtherHeadCode);
14766 while(Input[1] ==
' ')
14768 if(Input.Length() > 1)
14770 Input = Input.SubString(2, Input.Length() - 1);
14784 while(Input[Input.Length()] ==
' ')
14786 if(Input.Length() > 1)
14788 Input = Input.SubString(1, Input.Length() - 1);
14798 AnsiString Output =
"";
14799 bool DelimiterFound =
false;
14801 for(
int x = 1; x < Input.Length() + 1; x++)
14805 if(Input[x] ==
' ')
14810 if((Input[x] !=
',') && (Input[x] !=
';'))
14812 DelimiterFound =
false;
14813 Output = Output + Input[x];
14817 DelimiterFound =
true;
14818 Output = Output + Input[x];
14830 DelimiterFound =
false;
14831 for(
int x = Input.Length(); x > 0; x--)
14835 if(Input[x] ==
' ')
14840 if((Input[x] !=
',') && (Input[x] !=
';'))
14842 DelimiterFound =
false;
14843 Output = AnsiString(Input[x]) + Output;
14847 DelimiterFound =
true;
14848 Output = AnsiString(Input[x]) + Output;
14873 if((AVEntry0.
Command !=
"Snt") && (AVEntry0.
Command !=
"Snt-sh"))
14875 throw Exception(
"Error, first entry not 'Snt' or 'Snt-sh' in IsSNTEntryLocated");
14887 LocationName = LocRear;
14891 LocationName = LocFront;
14893 if(LocationName ==
"")
14914 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
14955 int RearPosition = 0, FrontPosition = 0, RearExitPos = 0;
14958 if(RearPosition < 0)
14965 if(FrontPosition < 0)
14976 for(
int x = 0; x < 4; x++)
14978 if(RearTrackElement.
Conn[x] == FrontPosition)
14993 TimetableMessage(GiveMessages,
"Front of train attempting to start on a continuation at: " + FrontElementStr);
15000 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + FrontElementStr);
15006 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + RearElementStr);
15011 if((RearType ==
Points) && (RearExitPos == 3))
15013 TimetableMessage(GiveMessages,
"Front of train attempting to start on element connected to diverging points at: " + RearElementStr);
15019 TimetableMessage(GiveMessages,
"Rear of train attempting to start on element connected to diverging points at: " + FrontElementStr);
15034 AnsiString(RearExitPos));
15045 int FrontPosition = RearTrackElement.
Conn[RearExitPos];
15047 int FrontEntryPos = RearTrackElement.
ConnLinkPos[RearExitPos];
15050 AnsiString RearName, FrontName;
15066 FrontName = FrontTrackElement.
ElementID;
15069 int LockedVectorNumber;
15239 "," + AnsiString(IncDigits));
15242 throw Exception(
"Error, last 2 characters not both digits and IncDigits > 0 in GetRepeatHeadCode");
15247 return(BaseHeadCode);
15249 int BaseDigits = BaseHeadCode.SubString(3, 2).ToInt();
15250 int NextRepeatDigits = BaseDigits + (IncDigits * RepeatNumber);
15252 while(NextRepeatDigits >= 100)
15254 NextRepeatDigits -= 100;
15256 AnsiString NextRepeatDigitsStr = AnsiString(NextRepeatDigits);
15258 if(NextRepeatDigitsStr.Length() < 2)
15260 NextRepeatDigitsStr = AnsiString(
'0') + NextRepeatDigitsStr;
15262 AnsiString NextRepeatHeadCode = BaseHeadCode.SubString(1, 2) + NextRepeatDigitsStr;
15265 return(NextRepeatHeadCode);
15273 AnsiString(RepeatNumber) +
"," + AnsiString(IncMinutes));
15274 TDateTime NextRepeatTime = BasicTime + TDateTime(((
double)(RepeatNumber * IncMinutes)) / 1440.0);
15276 return(NextRepeatTime);
15285 AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes));
15286 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
15287 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
15288 int RepeatSecs = RepeatMinutes * 60;
15290 if((ForwardSecs > (ReverseSecs - RepeatSecs + 10)) || (ForwardSecs < (ReverseSecs - RepeatSecs - 10)))
15325 NonRepeatingHeadCode);
15326 int ForwardCount = 0;
15327 int ReverseCount = 0;
15328 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
15338 if(TDEntry.
HeadCode == MainHeadCode)
15340 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15346 ForwardEntryPtr = &AVEntry;
15348 ForwardTDVectorNumber = x;
15353 if(ForwardCount == 0)
15356 throw Exception(
"Error, ForwardCount == 0 in CheckNonRepeatingShuttleLinksAndSetData after called with found values");
15358 if(ForwardCount > 1)
15360 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + NonRepeatingHeadCode +
" from a train whose headcode is " +
15370 if(TDEntry.
HeadCode == NonRepeatingHeadCode)
15372 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15379 ReverseEntryPtr = &AVEntry;
15380 ReverseTDVectorNumber = x;
15386 if(ReverseCount == 0)
15388 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + NonRepeatingHeadCode);
15393 if(ReverseCount > 1)
15395 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
15396 NonRepeatingHeadCode);
15401 if(((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh")) && (MainTrainDataPtr->
ActionVector.back().FormatType ==
Repeat))
15403 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle connecting train " + MainHeadCode +
" shouldn't have a repeat");
15408 if((ForwardEntryPtr->Command !=
"F-nshs") && (ForwardEntryPtr->Command !=
"Sns-fsh") && (MainTrainDataPtr->
ActionVector.back().FormatType !=
Repeat))
15410 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat item");
15415 if(ForwardEntryPtr->LocationName ==
"")
15417 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
15418 ". One or other service does not have a location set");
15425 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
15426 ". One or other service does not have a location set");
15431 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
15433 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + NonRepeatingHeadCode +
15434 " is at a different location to the referencing train " + MainHeadCode);
15439 if(ForwardEntryPtr->Command ==
"F-nshs")
15442 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
15444 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle in-link service " + MainHeadCode +
15445 " finish time not consistent with start time of shuttle service " + NonRepeatingHeadCode);
15451 if(ForwardEntryPtr->Command ==
"Fns-sh")
15455 MainTrainDataPtr->
ActionVector.back().RearStartOrRepeatMins, MainTrainDataPtr->
ActionVector.back().NumberOfRepeats))
15457 SecondPassMessage(GiveMessages,
"Error in timetable - service " + NonRepeatingHeadCode +
", which links out from shuttle service " + MainHeadCode +
15458 ", has the wrong start time. It should correspond to the finish time of the last shuttle.");
15464 if((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh"))
15467 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15469 SecondPassMessage(GiveMessages,
"Error in timetable - the non repeating link service " + NonRepeatingHeadCode +
15470 " appears in the same sequence as the corresponding shuttle service " + MainHeadCode);
15488 if(ForwardEntryPtr->Command ==
"Sns-sh")
15490 if(ReverseEntryPtr->
Command !=
"F-nshs")
15492 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'F-nshs' event for the 'Sns-sh' train whose headcode is " +
15493 MainHeadCode +
" and is a new shuttle service formed from the service with headcode " + NonRepeatingHeadCode);
15499 if(ForwardEntryPtr->Command ==
"F-nshs")
15501 if(ReverseEntryPtr->
Command !=
"Sns-sh")
15503 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns-sh' event for the 'F-nshs' train whose headcode is " +
15504 MainHeadCode +
" and forms a new shuttle service with headcode " + NonRepeatingHeadCode);
15511 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15522 if(ForwardEntryPtr->Command ==
"Sns-fsh")
15524 if(ReverseEntryPtr->
Command !=
"Fns-sh")
15527 "Error in timetable - unable to find a corresponding 'Fns-sh' event for the 'Sns-fsh' non-shuttle service whose headcode is " + MainHeadCode +
15528 " formed from a shuttle service with headcode " + NonRepeatingHeadCode);
15534 if(ForwardEntryPtr->Command ==
"Fns-sh")
15536 if(ReverseEntryPtr->
Command !=
"Sns-fsh")
15539 "Error in timetable - unable to find a corresponding 'Sns-fsh' event for the 'Fns-sh' shuttle service whose headcode is " + MainHeadCode +
15540 " and forms a new non-shuttle service with headcode " + NonRepeatingHeadCode);
15547 ForwardEntryPtr->NonRepeatingShuttleLinkEntryPtr = OtherTrainDataPtr;
15571 +
"," + AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes) +
"," + AnsiString(RepeatNumber));
15572 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
15573 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
15574 int RepeatSecs = RepeatMinutes * RepeatNumber * 60;
15576 if((ReverseSecs > (ForwardSecs + RepeatSecs + 10)) || (ReverseSecs < (ForwardSecs + RepeatSecs - 10)))
15600 throw Exception(
"Error - last entry in " + TDEntryPtr->
HeadCode +
" service is not a repeat - should have already found this error");
15603 AnsiString OriginalHeadCode = TDEntryPtr->
HeadCode;
15604 AnsiString LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
15606 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
15608 SecondPassMessage(GiveMessages,
"Error in timetable - last event in shuttle service " + TDEntryPtr->
HeadCode +
" is not 'Fns', 'Fns-sh' or 'Frh-sh'");
15613 while(LastActionCommand ==
"Fns")
15615 TDEntryPtr = (TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr;
15616 LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
15617 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
15620 "Error in timetable - last event in a continuation shuttle service (i.e links back to a shuttle) whose headcode is " + TDEntryPtr->
HeadCode +
15621 " is not 'Fns', 'Fns-sh' or 'Frh-sh'");
15628 if((TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr != ShuttleStartAddress)
15631 " is a shuttle finish, but it doesn't link back to the start of the original shuttle starting service " + OriginalHeadCode +
15632 ". The linking of two or more shuttles is not permitted.");
15652 ShowMessage(Message);
15670 ShowMessage(Message);
15709 AnsiString(ActionEventType) +
"," + LocationID);
15710 AnsiString BaseLog =
"", Prefix =
"", ErrorLog =
"", WarningStr =
"";
15715 Prefix =
" ERROR: ";
15718 Prefix =
" HELD: ";
15719 ErrorLog =
" can't enter railway, train obstructing entry position ";
15720 WarningStr =
" can't enter railway, train obstructing entry position ";
15725 Prefix =
" HELD: ";
15726 ErrorLog =
" can't enter railway, route set against it at entry position ";
15727 WarningStr =
" can't enter railway, route set against it at entry position ";
15732 Prefix =
" HELD: ";
15733 ErrorLog =
" can't be created, train obstructing ";
15734 WarningStr =
" can't be created, train obstructing ";
15739 Prefix =
" HELD: ";
15740 ErrorLog =
" can't be created on a locked route at ";
15741 WarningStr =
" can't be created on a locked route at ";
15746 Prefix =
" HELD: ";
15747 ErrorLog =
" can't enter on a locked route at ";
15748 WarningStr =
" can't enter on a locked route at ";
15753 Prefix =
" HELD: ";
15754 ErrorLog =
" can't be created, diverging points at ";
15755 WarningStr =
" can't be created, diverging points at ";
15760 ErrorLog =
" left railway unexpectedly at ";
15765 ErrorLog =
" left railway at an incorrect exit at ";
15770 ErrorLog =
" failed to split - location too short at ";
15771 WarningStr =
" failed to split, location too short at ";
15776 Prefix =
" HELD: ";
15777 ErrorLog =
" unable to split - other train obstructing at ";
15778 WarningStr =
" unable to split - other train obstructing at ";
15783 ErrorLog =
" stopped at buffers unexpectedly at position ";
15787 ErrorLog =
" failed to stop at ";
15792 ErrorLog =
" failed to split at ";
15797 ErrorLog =
" failed to be joined by other train at ";
15802 ErrorLog =
" failed to join other train at ";
15807 ErrorLog =
" failed to terminate at ";
15812 ErrorLog =
" failed to form new service at ";
15817 ErrorLog =
" failed to exit railway ";
15822 ErrorLog =
" failed to change direction at ";
15827 ErrorLog =
" failed to pass ";
15832 ErrorLog =
" facing buffers and unable to start at ";
15836 ErrorLog =
" DERAILED at position ";
15837 Prefix =
" DERAILMENT: ";
15842 ErrorLog =
" CRASHED INTO BUFFERS at ";
15843 Prefix =
" CRASH: ";
15848 ErrorLog =
" CRASHED INTO ROAD TRAFFIC AT A LEVEL CROSSING at ";
15849 Prefix =
" CRASH: ";
15854 ErrorLog =
" CRASHED INTO " + OtherHeadCode +
" at position ";
15855 Prefix =
" CRASH: ";
15859 else if(ActionEventType ==
FailSPAD)
15861 ErrorLog =
" PASSED SIGNAL AT DANGER at position ";
15862 Prefix =
" SPAD: ";
15867 ErrorLog =
"Signals reset ahead of train, route cancelled at position ";
15868 Prefix =
" SPAD RISK: ";
15873 ErrorLog =
" forced a route cancellation by occupying it incorrectly at ";
15877 Prefix =
" WARNING: ";
15878 ErrorLog =
" waiting to join " + OtherHeadCode +
" at ";
15879 WarningStr =
" waiting to join " + OtherHeadCode +
" at ";
15884 Prefix =
" WARNING: ";
15885 ErrorLog =
" waiting to be joined by " + OtherHeadCode +
" at ";
15886 WarningStr =
" waiting to be joined by " + OtherHeadCode +
" at ";
15924 std::ofstream OutFile(
"TrainData.csv");
15928 ShowMessage(
"Output file TrainData.csv failed to open");
15935 OutFile <<
"HeadCode" <<
',' <<
"Description" <<
',' <<
"StartSpeed" <<
',' <<
"MaxRunningSpeed" <<
',' <<
"NumberOfTrains" <<
'\n' <<
'\n';
15940 OutFile <<
',' <<
"FormatType" <<
',' <<
"EventTime" <<
',' <<
"ArrivalTime" <<
',' <<
"DepartureTime" <<
',' <<
"LocationName" <<
',' <<
"Command" <<
15941 ',' <<
"OtherHeadCode" <<
',' <<
"LinkedTrainEntryPtr" <<
',' <<
"RearStartOrRepeatMins" <<
',' <<
"FrontStartOrRepeatDigits" <<
',' <<
15942 "RepeatNumber" <<
'\n' <<
'\n';
15943 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15946 AnsiString TimetableEntryTypeStr;
15952 TimetableEntryTypeStr =
"NoFormat";
15958 TimetableEntryTypeStr =
"TimeLoc";
15964 TimetableEntryTypeStr =
"TimeTimeLoc";
15970 TimetableEntryTypeStr =
"TimeCmd";
15976 TimetableEntryTypeStr =
"StartNew";
15982 TimetableEntryTypeStr =
"TimeCmdHeadCode";
15988 TimetableEntryTypeStr =
"FinRemHere";
15994 TimetableEntryTypeStr =
"FNSShuttle";
16000 TimetableEntryTypeStr =
"SNTShuttle";
16006 TimetableEntryTypeStr =
"SNSShuttle";
16012 TimetableEntryTypeStr =
"SNSNonRepeatFromShuttle";
16018 TimetableEntryTypeStr =
"FSHNewService";
16024 TimetableEntryTypeStr =
"Repeat";
16030 TimetableEntryTypeStr =
"Default";
16041 OutFile <<
',' <<
',' <<
"Mass" <<
',' <<
"MaxBrakeRate" <<
',' <<
"PowerAtRail" <<
',' <<
"TrainID" <<
',' <<
"RunningEntry" <<
'\n' <<
'\n';
16042 for(
unsigned int y = 0; y <
TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
16045 AnsiString RunningEntryStr;
16051 RunningEntryStr =
"NotStarted";
16057 RunningEntryStr =
"Running";
16063 RunningEntryStr =
"Exited";
16067 OutFile <<
',' <<
',' << TOD.
TrainID <<
',' << RunningEntryStr.c_str() <<
',' <<
'\n';
16084 ShowMessage(Message);
16085 BaseTime = TDateTime::CurrentDateTime();
16099 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
16112 TTrain *NewTrain =
new TTrain(1, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
16114 for(
int x = 0; x < NumberOfTrains; x++)
16116 *NewTrain =
TTrain(2, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
16136 int NumberOfTrains;
16143 for(
int x = 0; x < NumberOfTrains; x++)
16180 for(
int x = 0; x < LockedRouteVectorSize; x++)
16187 LockedRouteObject.
LockStartTime = TDateTime(LockStartTimeDouble);
16198 int LockedRouteVectorSize;
16205 for(
int x = 0; x < LockedRouteVectorSize; x++)
16263 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
16271 ContinuationAutoSigObject.
PassoutTime = TDateTime(PassoutTimeDouble);
16282 int ContinuationAutoSigVectorSize;
16289 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
16359 if(AVFirstEntry.
Command ==
"Snt")
16383 CTEMMP.second = CTEEntry;
16390 throw Exception(
"Error, Last ActionVectorEntry not a repeat in BuildContinuationTrainExpectationMultiMap");
16398 CTEMMP.second = CTEEntry;
16419 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
16436 if((VecPos < 0) || (VecPos >= (
int)
TrainVector.size()))
16438 throw Exception(
"Out of Range Error, vector size: " + AnsiString(
TrainVector.size()) +
", VecPos: " + AnsiString(VecPos) +
" in TrainVectorAt");
16449 AnsiString RetStr =
"", PartStr =
"";
16564 AnsiString TTFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
16568 TTFileName = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
16570 AnsiString ShortTTName =
"";
16572 for(
int x = TTFileName.Length(); x > 0; x--)
16574 if(TTFileName[x] ==
'\\')
16576 ShortTTName = TTFileName.SubString(x + 1, TTFileName.Length() - x - 4);
16581 ShowMessage(
"Creates two timetables named " + ShortTTName +
16582 " in the 'Formatted timetables' folder, one in service order in '.csv' format, and one in chronological order in '.txt' format");
16584 Screen->Cursor = TCursor(-11);
16586 AnsiString FormatNoDPStr =
"#######0";
16587 AnsiString TableTitle =
"", TimetableTimeStr =
"", MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"", FirstHeadCode =
"", Header =
"";
16590 TableTitle =
"Railway: " + RailwayTitle +
"; Timetable: " + TimetableTitle +
"; Start time: " + TimetableTimeStr;
16597 MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"";
16599 if(TrainDataEntry.
Mass > 0)
16601 MassStr =
"; Mass " + AnsiString::FormatFloat(FormatNoDPStr, ((
double)TrainDataEntry.
Mass) / 1000) +
"Te; ";
16605 PowerStr =
"Power " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
PowerAtRail / 1000 / 0.8) +
"kW; ";
16609 BrakeStr =
"Brake force " + AnsiString::FormatFloat(FormatNoDPStr, (TrainDataEntry.
MaxBrakeRate * TrainDataEntry.
Mass / 9810)) +
"Te; ";
16613 MaxSpeedStr =
"Maximum speed " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
MaxRunningSpeed) +
" km/h";
16615 FirstHeadCode = TrainDataEntry.
HeadCode;
16616 int IncDigits = 0, IncMinutes = 0;
16618 if(!ActionVector.empty())
16620 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
16622 IncDigits = ActionVector.at(ActionVector.size() - 1).FrontStartOrRepeatDigits;
16623 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
16631 if((TrainDataEntry.
Description !=
"") && (MassStr !=
""))
16633 OneTTLine.
Header = TrainDataEntry.
Description + MassStr + PowerStr + BrakeStr + MaxSpeedStr;
16641 for(
unsigned int z = 0; z < ActionVector.size(); z++)
16646 AnsiString PartStr =
"", TimeStr =
"";
16663 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
16667 PartStr =
"Created at " + ActionVectorEntry.
LocationName;
16677 PartStr =
"Enters at " + LocName;
16690 PartStr =
"Created at " + LocName;
16704 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
16709 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
16715 else if(ActionVectorEntry.
Command ==
"Sfs")
16717 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" split from";
16721 else if(ActionVectorEntry.
Command ==
"Sns")
16723 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
16731 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
16737 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
16745 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
16748 AnsiString FirstHeadCode = TDE->
HeadCode;
16752 TimeStr =
GetRepeatHeadCode(36, FirstHeadCode, LastRepeatNumber, IncrementalDigits) +
" at " +
16764 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
16766 OneTTEntry.
Action = PartStr;
16767 OneTTEntry.
Time = TimeStr;
16769 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
16774 PartStr =
"Arrives & departs " + ActionVectorEntry.
LocationName;
16780 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
16785 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
16793 else if(ActionVectorEntry.
Command ==
"jbo")
16795 PartStr =
"Joined at " + ActionVectorEntry.
LocationName +
" by";
16799 else if(ActionVectorEntry.
Command ==
"fsp")
16801 PartStr =
"Splits from front at " + ActionVectorEntry.
LocationName +
" to form";
16805 else if(ActionVectorEntry.
Command ==
"rsp")
16807 PartStr =
"Splits from rear at " + ActionVectorEntry.
LocationName +
" to form";
16811 else if(ActionVectorEntry.
Command ==
"cdt")
16813 PartStr =
"Changes direction at " + ActionVectorEntry.
LocationName;
16819 if(ActionVectorEntry.
Command ==
"Fns")
16821 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
16825 else if(ActionVectorEntry.
Command ==
"F-nshs")
16827 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
16833 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service ";
16840 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
16846 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
16853 PartStr =
"Terminates shuttle service at " + ActionVectorEntry.
LocationName;
16858 else if(ActionVectorEntry.
Command ==
"Frh")
16860 PartStr =
"Terminates at " + ActionVectorEntry.
LocationName;
16865 if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
16869 else if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
16879 else if(ActionVectorEntry.
Command ==
"Fer")
16881 AnsiString AllowedExits;
16885 else if(ActionVectorEntry.
Command ==
"Fjo")
16887 PartStr =
"At " + ActionVectorEntry.
LocationName +
" joins";
16896 OneTTEntry.
Action = PartStr;
16897 OneTTEntry.
Time = TimeStr;
16904 AllTTTrains->push_back(OneTTLine);
16908 std::ofstream TTFile(TTFileName.c_str());
16912 StopTTClockMessage(64,
"Formatted timetable file failed to open - can't be created");
16913 delete AllTTTrains;
16948 TTFile << TableTitle.c_str() <<
'\n' <<
'\n';
16949 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
16951 TTFile << AllTTTrains->at(x).Header.c_str();
16954 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
16956 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
16958 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str() <<
',';
16962 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str();
16965 TTFile <<
'\n' <<
'\n';
16967 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.size(); z++)
16969 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.at(z).Action.c_str() <<
',';
16970 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
16972 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
16974 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str() <<
',';
16978 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str();
16983 TTFile <<
'\n' <<
'\n';
16988 AnsiString TTFileName2 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
16990 TTFileName2 = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName2 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".txt";
16992 std::ofstream TTFile2(TTFileName2.c_str());
16996 StopTTClockMessage(67,
"Chronological timetable file failed to open - can't be created");
16997 delete AllTTTrains;
17001 typedef std::multimap<AnsiString, AnsiString>TAnsiMultiMap;
17002 std::multimap<AnsiString, AnsiString>::iterator AMMIT;
17003 std::pair<AnsiString, AnsiString>AnsiMultiMapEntry;
17005 TAnsiMultiMap *TAMM =
new TAnsiMultiMap;
17010 TTFile2 << TableTitle.c_str() <<
'\n' <<
'\n';
17011 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
17013 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17015 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.size(); z++)
17017 bool GiveMessagesFalse =
false;
17018 AnsiString TimeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time;
17019 AnsiString HeadCodeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode;
17020 AnsiString ActionString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Action;
17025 AnsiString OtherHeadCode = TimeString.SubString(1, 4);
17026 TimeString = TimeString.SubString(9, 5);
17027 ActionString +=
" " + OtherHeadCode;
17029 if(TimeString.SubString(1, 7) ==
"End at ")
17032 TimeString = TimeString.SubString(8, 5);
17034 AnsiString OneLine = TimeString +
' ' + HeadCodeString +
' ' + ActionString +
'\n';
17035 AnsiMultiMapEntry.first = TimeString;
17036 AnsiMultiMapEntry.second = OneLine;
17037 TAMM->insert(AnsiMultiMapEntry);
17042 for(AMMIT = TAMM->begin(); AMMIT != TAMM->end(); AMMIT++)
17044 TTFile2 << (AMMIT->second).c_str();
17046 delete AllTTTrains;
17055 bool AtLocChecked,
bool DirChecked,
int ArrRange,
int DepRange)
17059 bool AnalysisError =
false;
17060 AnsiString SequenceLog =
"SequenceLog\n";
17102 TTrainDataVector::iterator TDVIt, TDVCopyIt;
17104 int IteratorNumber = 0;
17105 AnsiString AnsiSuffix =
"";
17110 for(TDVCopyIt = TrainDataVectorCopy.begin() + IteratorNumber; TDVCopyIt != TrainDataVectorCopy.end(); TDVCopyIt++)
17112 if(TDVCopyIt->ServiceReference == TDVIt->ServiceReference)
17115 AnsiSuffix = AnsiString(Suffix);
17116 TDVCopyIt->ServiceReference = TDVIt->ServiceReference +
"/" + AnsiSuffix;
17120 SequenceLog +=
"1\n";
17123 std::pair<AnsiString, TServiceCallingLocsList> AllServiceCallingLocsEntry;
17124 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
17129 ServiceCallingLocsList.clear();
17130 if(ActionVector.empty())
17134 if(ActionVector.at(0).SignallerControl)
17138 for(
unsigned int z = 0; z < ActionVector.size(); z++)
17156 int HLoc = TE.
HLoc;
17157 int VLoc = TE.
VLoc;
17158 AnsiString HString;
17159 AnsiString VString;
17162 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
17166 HString = AnsiString(HLoc);
17170 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
17174 VString = AnsiString(VLoc);
17176 ServiceCallingLocsList.push_back(HString +
'-' + VString);
17199 else if(AVE.
Command ==
"cdt")
17201 if(ActionVector.at(z-1).SequenceType ==
Start)
17205 else if(ActionVector.at(z+1).SequenceType ==
Finish)
17212 ServiceCallingLocsList.push_back(
"%%%" + TimeString);
17221 ServiceCallingLocsList.push_back(LName);
17225 int HLoc = TE.
HLoc;
17226 int VLoc = TE.
VLoc;
17227 AnsiString HString;
17228 AnsiString VString;
17231 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
17235 HString = AnsiString(HLoc);
17239 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
17243 VString = AnsiString(VLoc);
17245 ServiceCallingLocsList.push_back(HString +
'-' + VString);
17249 AllServiceCallingLocsEntry.second = ServiceCallingLocsList;
17253 SequenceLog +=
"2\n";
17282 ShowMessage(
"Unable to create a program-readable timetable - please check the timetable file validity");
17288 bool NumPlatsAtThisLocCalculated =
false, ArrivalsPrinted =
false, DeparturesPrinted =
false, AtLocsPrinted =
false;
17289 AnsiString PreviousService =
"", PreviousServiceAndRepeatNumTotalOutput =
"", BasicTime =
"", MinuteString =
"", LastAnsiTime =
"";
17290 int NumTrains = 0, NumPlats = 0, LastFrhCount = 0, FrhCount = 0, NumTrainsAtLoc = 0;
17292 SequenceLog +=
"3\n";
17294 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
17299 TDateTime LastTDTime;
17300 int IncMinutes = 0;
17302 if(ActionVector.empty())
17306 if(ActionVector.at(0).SignallerControl)
17310 if(AVLast->FormatType ==
Repeat)
17312 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
17320 if(AVLast->ArrivalTime != TDateTime(-1))
17322 LastTDTime = AVLast->ArrivalTime;
17324 else if(AVLast->EventTime != TDateTime(-1))
17326 LastTDTime = AVLast->EventTime;
17345 SequenceLog +=
"4\n";
17377 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
17382 int IncMinutes = 0;
17384 if(ActionVector.empty())
17388 if(ActionVector.at(0).SignallerControl)
17392 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
17394 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
17396 for(
int y = 0; y < NumTrains; y++)
17410 for(
unsigned int z = 0; z < ActionVector.size(); z++)
17425 LocServiceTimesVector.push_back(TLSTEntry);
17428 AnsiString IncTime =
"", FoundStopTime =
"";
17429 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
17431 if(ActionVector.at(a).FormatType ==
TimeLoc)
17436 if(ActionVector.at(a).SequenceType ==
Finish)
17442 if(FoundStopTime ==
"")
17444 throw Exception(
"Failure to determine FoundStopTime for located Snt");
17446 int WhileCount = 0;
17455 if(IncTime >= FoundStopTime)
17459 LocServiceTimesVector.push_back(TLSTEntry);
17460 if(WhileCount > 2000)
17462 throw Exception(
"While loop failed to break in 2000 loops for located Snt");
17475 int HLoc = TE.
HLoc;
17476 int VLoc = TE.
VLoc;
17477 AnsiString HString;
17478 AnsiString VString;
17481 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
17485 HString = AnsiString(HLoc);
17489 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
17493 VString = AnsiString(VLoc);
17495 TLSTEntry.
Location = HString +
'-' + VString;
17499 LocServiceTimesVector.push_back(TLSTEntry);
17507 LocServiceTimesVector.push_back(TLSTEntry);
17509 AnsiString IncTime =
"", FoundStopTime =
"";
17510 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
17512 if(ActionVector.at(a).FormatType ==
TimeLoc)
17517 if(ActionVector.at(a).SequenceType ==
Finish)
17523 if(FoundStopTime ==
"")
17525 throw Exception(
"Failure to determine FoundStopTime for SequenceType == Start");
17527 int WhileCount = 0;
17536 if(IncTime >= FoundStopTime)
17540 LocServiceTimesVector.push_back(TLSTEntry);
17541 if(WhileCount > 2000)
17543 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == Start");
17553 bool SkipAddingMinutes =
false;
17556 LocServiceTimesVector.push_back(TLSTEntry);
17558 AnsiString IncTime =
"", FoundStopTime =
"";
17559 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
17561 if(ActionVector.at(a).FormatType ==
TimeLoc)
17566 if(ActionVector.at(a).SequenceType ==
Finish)
17569 if((a <= (z + 2)) && (FoundStopTime == TLSTEntry.
ArrTime) && ((ActionVector.at(a).LinkedTrainEntryPtr > 0) || (ActionVector.at(a).NonRepeatingShuttleLinkEntryPtr > 0)))
17573 LocServiceTimesVector.pop_back();
17574 SkipAddingMinutes =
true;
17579 if(FoundStopTime ==
"")
17581 throw Exception(
"Failure to determine FoundStopTime for SequenceType == Start");
17583 if(!SkipAddingMinutes)
17585 int WhileCount = 0;
17594 if(IncTime >= FoundStopTime)
17598 LocServiceTimesVector.push_back(TLSTEntry);
17599 if(WhileCount > 2000)
17601 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == Start");
17610 if((TLSTEntry.
Location == LocServiceTimesVector.back().Location) && (TLSTEntry.
ServiceAndRepeatNum == LocServiceTimesVector.back().ServiceAndRepeatNum))
17612 if(TLSTEntry.
DepTime == LocServiceTimesVector.back().ArrTime)
17614 TLSTEntry.
ArrTime = LocServiceTimesVector.back().ArrTime;
17615 LocServiceTimesVector.pop_back();
17616 LocServiceTimesVector.push_back(TLSTEntry);
17621 LocServiceTimesVector.push_back(TLSTEntry);
17627 LocServiceTimesVector.push_back(TLSTEntry);
17646 LocServiceTimesVector.push_back(TLSTEntry);
17650 AnsiString TempDepTime = TLSTEntry.
DepTime;
17652 LocServiceTimesVector.push_back(TLSTEntry);
17654 while(TLSTEntry.
AtLocTime < TempDepTime)
17659 TLSTEntry.
DepTime = TempDepTime;
17660 LocServiceTimesVector.push_back(TLSTEntry);
17664 LocServiceTimesVector.push_back(TLSTEntry);
17675 LocServiceTimesVector.push_back(TLSTEntry);
17678 LocServiceTimesVector.push_back(TLSTEntry);
17695 AnsiString HString;
17696 AnsiString VString;
17699 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
17703 HString = AnsiString(HLoc);
17707 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
17711 VString = AnsiString(VLoc);
17713 TLSTEntry.
Location = HString +
'-' + VString;
17715 LocServiceTimesVector.push_back(TLSTEntry);
17720 AnsiString FrhTime;
17721 if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
17725 else if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
17733 LocServiceTimesVector.push_back(TLSTEntry);
17739 LocServiceTimesVector.push_back(TLSTEntry);
17744 else if(AVE.
Command ==
"Frh-sh")
17746 if(y == NumTrains - 1)
17752 LocServiceTimesVector.push_back(TLSTEntry);
17758 LocServiceTimesVector.push_back(TLSTEntry);
17771 SequenceLog +=
"5\n";
17802 TLocServiceTimesVector::iterator Ptr1, Ptr2;
17805 AnsiString TTFileName3 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17806 TTFileName3 = CurDir +
"\\Formatted timetables\\Conflict Analysis " + TTFileName3 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
17808 std::ofstream TTFile3(TTFileName3.c_str());
17812 ShowMessage(
"Conflict Analysis file failed to open - can't be created");
17816 if(LocServiceTimesVector.empty())
17818 ShowMessage(
"No timetabled services found");
17820 DeleteFile(TTFileName3);
17824 TTFile3 <<
"Timetable analysis for timetable: '" + TimetableTitle +
"' in conjunction with railway: '" + RailwayTitle +
"'\n";
17825 TTFile3 <<
"See user manual or on-screen help section 5.12 for detailed information.\n\n\n";
17826 SequenceLog +=
"6\n";
17876 Ptr1 = LocServiceTimesVector.begin();
17878 while(Ptr2 != LocServiceTimesVector.end())
17880 while(Ptr2->Location == Ptr1->Location)
17883 if(Ptr2 == LocServiceTimesVector.end())
17890 if(Ptr2 != LocServiceTimesVector.end())
17898 TTFile3 <<
"Arrival & pass analysis: an asterisk means that the number of same approach code arrivals and passes is equal to or greater than the number of platforms.\n";
17899 TTFile3 <<
"If the total number of arrivals and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
17900 MinuteString =
" minutes";
17901 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
17904 MinuteString =
" minute";
17906 TTFile3 <<
"Location,Number of,Number of,Services arriving within " << AnsiString(ArrRange) << MinuteString <<
" with their arrival times and approach codes\n";
17907 TTFile3 <<
",Platforms,Trains\n\n";
17909 Ptr1 = LocServiceTimesVector.begin();
17911 while(Ptr2 != LocServiceTimesVector.end())
17913 PreviousService =
"";
17914 NumTrainsAtLoc = 0;
17915 ServiceAndRepeatNumTotal =
"";
17917 NumPlatsAtThisLocCalculated =
false;
17919 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
17921 PreviousService =
"";
17922 NumTrainsAtLoc = 0;
17923 ServiceAndRepeatNumTotal =
"";
17925 NumPlatsAtThisLocCalculated =
false;
17929 if(Ptr2 == LocServiceTimesVector.end())
17934 if(Ptr2 == LocServiceTimesVector.end())
17938 while(Ptr2->Location == Ptr1->Location)
17940 PreviousService =
"";
17941 NumTrainsAtLoc = 0;
17942 ServiceAndRepeatNumTotal =
"";
17943 BasicTime = Ptr1->ArrTime;
17944 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
17948 while(!
WithinTimeRange(0, BasicTime, Ptr2->ArrTime, ArrRange) || ((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
"")))
17950 BasicTime = Ptr2->ArrTime;
17953 if(Ptr2 == LocServiceTimesVector.end())
17957 if(Ptr2->Location != Ptr1->Location)
17962 if(Ptr2 == LocServiceTimesVector.end())
17966 if(Ptr2->Location != Ptr1->Location)
17972 if((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
""))
17976 if(!NumPlatsAtThisLocCalculated)
17979 NumPlatsAtThisLocCalculated =
true;
17981 if(Ptr1->ServiceAndRepeatNum != PreviousService)
17983 if(ServiceAndRepeatNumTotal ==
"")
17985 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
17986 NumTrainsAtLoc = 1;
17990 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
17993 PreviousService = Ptr2->ServiceAndRepeatNum;
17994 if(ServiceAndRepeatNumTotal ==
"")
17996 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
17997 NumTrainsAtLoc = 1;
18001 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
18005 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(2, BasicTime, Ptr2->ArrTime, ArrRange)))
18007 int MaxNumberOfSameDirections = 0;
18008 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
true, AnalysisError, MaxNumberOfSameDirections);
18013 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
18017 AnsiString Asterisk =
"";
18018 if(MaxNumberOfSameDirections >= NumPlats)
18023 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
18024 ArrivalsPrinted =
true;
18025 ServiceAndRepeatNumTotal =
"";
18027 if(Ptr2 == LocServiceTimesVector.end())
18031 if(Ptr2->Location != Ptr1->Location)
18036 if(Ptr2 == LocServiceTimesVector.end())
18042 if(!ArrivalsPrinted)
18044 TTFile3 <<
"Nothing to report for arrivals";
18049 SequenceLog +=
"7\n";
18054 Ptr1 = LocServiceTimesVector.begin();
18056 while(Ptr2 != LocServiceTimesVector.end())
18058 while(Ptr2->Location == Ptr1->Location)
18061 if(Ptr2 == LocServiceTimesVector.end())
18068 if(Ptr2 != LocServiceTimesVector.end())
18075 TTFile3 <<
"Departure & pass analysis: an asterisk means that the number of same exit code departures and passes is equal to or greater than the number of platforms.\n";
18076 TTFile3 <<
"If the total number of departures and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
18077 MinuteString =
" minutes";
18078 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
18081 MinuteString =
" minute";
18083 TTFile3 <<
"Location,Number of,Number of,Services departing within " << AnsiString(DepRange) << MinuteString <<
" with their departure times and exit codes\n";
18084 TTFile3 <<
",Platforms,Trains\n\n";
18086 Ptr1 = LocServiceTimesVector.begin();
18088 while(Ptr2 != LocServiceTimesVector.end())
18090 PreviousService =
"";
18091 NumTrainsAtLoc = 0;
18092 ServiceAndRepeatNumTotal =
"";
18094 NumPlatsAtThisLocCalculated =
false;
18096 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
18098 PreviousService =
"";
18099 NumTrainsAtLoc = 0;
18100 ServiceAndRepeatNumTotal =
"";
18102 NumPlatsAtThisLocCalculated =
false;
18106 if(Ptr2 == LocServiceTimesVector.end())
18111 if(Ptr2 == LocServiceTimesVector.end())
18115 while(Ptr2->Location == Ptr1->Location)
18117 PreviousService =
"";
18118 NumTrainsAtLoc = 0;
18119 ServiceAndRepeatNumTotal =
"";
18120 BasicTime = Ptr1->DepTime;
18121 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
18125 while(!
WithinTimeRange(3, BasicTime, Ptr2->DepTime, DepRange) || ((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
"")))
18127 BasicTime = Ptr2->DepTime;
18130 if(Ptr2 == LocServiceTimesVector.end())
18134 if(Ptr2->Location != Ptr1->Location)
18139 if(Ptr2 == LocServiceTimesVector.end())
18143 if(Ptr2->Location != Ptr1->Location)
18149 if((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
""))
18153 if(!NumPlatsAtThisLocCalculated)
18156 NumPlatsAtThisLocCalculated =
true;
18158 if(Ptr1->ServiceAndRepeatNum != PreviousService)
18160 if(ServiceAndRepeatNumTotal ==
"")
18162 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
18163 NumTrainsAtLoc = 1;
18167 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
18170 PreviousService = Ptr2->ServiceAndRepeatNum;
18171 if(ServiceAndRepeatNumTotal ==
"")
18173 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
18174 NumTrainsAtLoc = 1;
18178 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
18182 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(5, BasicTime, Ptr2->DepTime, DepRange)))
18184 int MaxNumberOfSameDirections = 0;
18185 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(3, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
false, AnalysisError, MaxNumberOfSameDirections);
18190 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
18194 AnsiString Asterisk =
"";
18195 if(MaxNumberOfSameDirections >= NumPlats)
18200 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
18201 DeparturesPrinted =
true;
18202 ServiceAndRepeatNumTotal =
"";
18204 if(Ptr2 == LocServiceTimesVector.end())
18208 if(Ptr2->Location != Ptr1->Location)
18213 if(Ptr2 == LocServiceTimesVector.end())
18219 if(!DeparturesPrinted)
18221 TTFile3 <<
"Nothing to report for departures";
18226 SequenceLog +=
"8\n";
18233 Ptr1 = LocServiceTimesVector.begin();
18235 while(Ptr2 != LocServiceTimesVector.end())
18237 while(Ptr2->Location == Ptr1->Location)
18240 if(Ptr2 == LocServiceTimesVector.end())
18247 if(Ptr2 != LocServiceTimesVector.end())
18254 TTFile3 <<
"Trains present at location analysis: an asterisk means that the number of trains at the location is greater than the number of platforms.\n\n";
18255 TTFile3 <<
"Location,Number of,Number of,Time,Services at the location at that time\n";
18256 TTFile3 <<
",Platforms,Trains,\n\n";
18257 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
18258 Ptr1 = LocServiceTimesVector.begin();
18260 while(Ptr2 != LocServiceTimesVector.end())
18262 PreviousService =
"";
18263 ServiceAndRepeatNumTotal =
"";
18264 NumTrainsAtLoc = 0;
18266 NumPlatsAtThisLocCalculated =
false;
18269 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
18271 PreviousService =
"";
18272 ServiceAndRepeatNumTotal =
"";
18273 NumTrainsAtLoc = 0;
18275 NumPlatsAtThisLocCalculated =
false;
18279 if(Ptr2 == LocServiceTimesVector.end())
18284 if(Ptr2 == LocServiceTimesVector.end())
18288 while(Ptr2->Location == Ptr1->Location)
18290 if(Ptr1->FrhMarker ==
"Frh")
18293 Ptr1->FrhMarker =
"FrhCounted";
18295 PreviousService =
"";
18296 NumTrainsAtLoc = 0;
18297 ServiceAndRepeatNumTotal =
"";
18298 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
18302 while((Ptr2->AtLocTime != Ptr1->AtLocTime) || ((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
"")))
18305 if(Ptr1->FrhMarker ==
"Frh")
18308 Ptr1->FrhMarker =
"FrhCounted";
18311 if(Ptr2 == LocServiceTimesVector.end())
18315 if(Ptr2->Location != Ptr1->Location)
18320 if(Ptr2 == LocServiceTimesVector.end())
18324 if(Ptr2->Location != Ptr1->Location)
18328 while(Ptr2->AtLocTime == Ptr1->AtLocTime)
18330 if((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
""))
18334 if(!NumPlatsAtThisLocCalculated)
18337 NumPlatsAtThisLocCalculated =
true;
18339 if(Ptr1->ServiceAndRepeatNum != PreviousService)
18341 if(ServiceAndRepeatNumTotal ==
"")
18343 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum;
18344 NumTrainsAtLoc = 1;
18348 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum;
18351 PreviousService = Ptr2->ServiceAndRepeatNum;
18352 if(ServiceAndRepeatNumTotal ==
"")
18354 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum;
18355 NumTrainsAtLoc = 1;
18359 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum;
18362 if(Ptr1->FrhMarker ==
"Frh")
18365 Ptr1->FrhMarker =
"FrhCounted";
18368 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (Ptr2->AtLocTime != Ptr1->AtLocTime))
18372 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTAtLoc(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc);
18374 if((NumTrainsAtLoc > 1) && ((FrhCount < NumTrainsAtLoc) || (FrhCount != LastFrhCount)))
18376 AnsiString Asterisk =
"";
18377 if(NumTrainsAtLoc > NumPlats)
18384 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
18386 else if(FrhCount == 1)
18388 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (1 remains here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
18392 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (" << FrhCount <<
" remain here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
18394 LastFrhCount = FrhCount;
18395 PreviousServiceAndRepeatNumTotalOutput = ServiceAndRepeatNumTotalOutput;
18396 AtLocsPrinted =
true;
18397 ServiceAndRepeatNumTotal =
"";
18400 if(Ptr2 == LocServiceTimesVector.end())
18404 if(Ptr2->Location != Ptr1->Location)
18409 if(Ptr2 == LocServiceTimesVector.end())
18417 TTFile3 <<
"Nothing to report for trains at locations";
18422 SequenceLog +=
"9\n";
18452 TTrainDataEntry SingleServiceEntry, PartServiceEntry, NewPartServiceEntry, TempEntry;
18457 TTFile3 <<
"Train direction analysis - consisting of train facing directions on creation and possible missing or questionable changes of direction:\n\n";
18458 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
18466 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
18468 SingleServiceEntry = TDE;
18470 for(
unsigned int y = 0; y < SSAV.size(); y++)
18472 if((SSAV.at(y).Command ==
"Fjo") || (SSAV.at(y).Command ==
"Frh") || (SSAV.at(y).Command ==
"Fer") || (SSAV.at(y).Command ==
"Frh-sh"))
18474 SingleServiceVector.push_back(SingleServiceEntry);
18477 else if((SSAV.at(y).Command ==
"fsp") || (SSAV.at(y).Command ==
"rsp"))
18479 PartServiceEntry = TDE;
18481 for(
unsigned int z = 0; z <= y; z++)
18486 PartServiceEntry.
ActionVector.at(z).Command =
"chr-sp";
18487 PartServiceEntry.
ActionVector.at(z).OtherHeadCode = PartServiceEntry.
ActionVector.at(z).LinkedTrainEntryPtr->ServiceReference;
18490 PartServiceVector.push_back(PartServiceEntry);
18491 if(SSAV.at(y).Command ==
"fsp")
18493 SSAV.at(y).Command =
"Front split - original service continues below";
18494 SSAV.at(y).OtherHeadCode =
"";
18496 if(SSAV.at(y).Command ==
"rsp")
18498 SSAV.at(y).Command =
"Rear split - original service continues below";
18499 SSAV.at(y).OtherHeadCode =
"";
18503 else if(SSAV.at(y).Command ==
"Fns")
18505 SSAV.at(y).Command =
"chr-Fns";
18506 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
18507 PartServiceVector.push_back(SingleServiceEntry);
18510 else if(SSAV.at(y).Command ==
"Fns-sh")
18512 SSAV.at(y).Command =
"chr-Fns-sh";
18513 SSAV.at(y).OtherHeadCode = SSAV.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
18514 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
18515 PartServiceVector.push_back(SingleServiceEntry);
18518 else if(SSAV.at(y).Command ==
"F-nshs")
18520 SSAV.at(y).Command =
"chr-F-nshs";
18521 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
18522 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
18523 PartServiceVector.push_back(SingleServiceEntry);
18529 SequenceLog +=
"10\n";
18533 AnsiString NextRef;
18534 while(!PartServiceVector.empty())
18536 PartServiceEntry = PartServiceVector.at(0);
18537 for(
unsigned int y = 0; y < PartServiceEntry.
ActionVector.size(); y++)
18539 if(PartServiceEntry.
ActionVector.at(y).Command.SubString(1,3) ==
"chr")
18541 NextRef = PartServiceEntry.
ActionVector.at(y).OtherHeadCode;
18545 bool FinishType =
true, FoundFlag =
false;
18552 for(
unsigned int y = 1; y < TempEntry.
ActionVector.size(); y++)
18556 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
18560 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
18566 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
18567 SingleServiceVector.push_back(PartServiceVector.at(0));
18568 PartServiceVector.erase(&PartServiceVector.at(0));
18573 NewPartServiceEntry = PartServiceVector.at(0);
18577 PartServiceVector.push_back(NewPartServiceEntry);
18580 TempEntry.
ActionVector.at(y).Command =
"Front split - original service continues below";
18585 TempEntry.
ActionVector.at(y).Command =
"Rear split - original service continues below";
18588 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
18590 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns")
18593 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
18595 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
18598 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns-sh")
18601 TempEntry.
ActionVector.at(y).OtherHeadCode = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
18602 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
18603 NextRef = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
18604 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
18607 else if(TempEntry.
ActionVector.at(y).Command ==
"F-nshs")
18611 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
18612 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
18613 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
18621 SequenceLog += +
"11\n";
18622 throw Exception(
"Unable to find service reference " + NextRef +
" Last ref checked = " + TempEntry.
ServiceReference);
18626 if(!PartServiceVector.empty())
18628 SequenceLog +=
"12\n";
18629 throw Exception(
"PartServiceVector should be empty here - size = " + PartServiceVector.size());
18631 SequenceLog +=
"13\n";
18676 bool BufferFacingUnReportedFlag =
true;
18677 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
18683 SequenceLog +=
"13a\n";
18684 throw Exception(
"Repeat entry present in SingleServiceVector at position " + x);
18687 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
18689 bool BufferFlag =
false;
18690 int FrontTVPos = AV.at(0).FrontStartOrRepeatDigits;
18691 int RearTVPos = AV.at(0).RearStartOrRepeatMins;
18692 AnsiString FrontLocName = AV.at(0).LocationName;
18693 int NextEntryPos, NextExitPos;
18696 if(ThisElement.
Conn[0] == RearTVPos)
18700 else if(ThisElement.
Conn[1] == RearTVPos)
18704 else if(ThisElement.
Conn[2] == RearTVPos)
18708 else if(ThisElement.
Conn[3] == RearTVPos)
18720 if(ThisElement.
Conn[ThisExitPos] == -1)
18722 SequenceLog =
"13b\n";
18723 throw Exception(
"ThisElement connects to -1 for " + TDE.
ServiceReference);
18726 NextEntryPos = ThisElement.
ConnLinkPos[ThisExitPos];
18727 if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 0) || (NextEntryPos == 2)))
18729 BufferFlag =
false;
18734 BufferFlag =
false;
18739 BufferFlag =
false;
18747 else if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 1) || (NextEntryPos == 3)))
18749 ThisElement = NextElement;
18755 if(NextEntryPos == 0)
18759 else if(NextEntryPos == 1)
18763 else if(NextEntryPos == 2)
18767 else if(NextEntryPos == 3)
18772 ThisElement = NextElement;
18773 ThisExitPos = NextExitPos;
18778 if(BufferFacingUnReportedFlag)
18780 TTFile3 <<
"Train facing direction on creation analysis:-\n\n";
18781 BufferFacingUnReportedFlag =
false;
18783 TTFile3 <<
"Service " + TDE.
ServiceReference +
" facing buffers on creation\n";
18787 if(BufferFacingUnReportedFlag)
18789 TTFile3 <<
"Nothing to report for train facing directions\n\n";
18795 SequenceLog +=
"13c\n";
18798 AnsiString LocationNameToBeChecked =
"";
18799 bool MissingcdtUnreportedFlag =
true;
18801 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
18804 unsigned int y = 0;
18805 int FirstInstance = 9999, SecondInstance = 9999;
18806 bool FullBreak =
false;
18807 MarkerList.clear();
18814 while((y < TDEntry.
ActionVector.size()) && !FullBreak)
18823 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
18825 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
18830 (AVEntry.
Command ==
"Frh-sh"))
18845 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
18851 if(TDEntry.
ActionVector.at(a).LocationName == LocationNameToBeChecked)
18853 SecondInstance = a;
18855 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
18857 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
18859 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
18862 if(MissingcdtUnreportedFlag)
18864 TTFile3 <<
"Possibly missing changes of direction - these will be missing unless the service travels in a loop back to the locations marked:-\n\n";
18866 TTFile3 << LocationNameToBeChecked <<
" is listed twice with no direction change between in service sequence: " << Sequence <<
"\n\n";
18867 MarkerList.push_back(FirstInstance);
18868 MarkerList.push_back(SecondInstance);
18870 MissingcdtUnreportedFlag =
false;
18881 if(MissingcdtUnreportedFlag)
18883 TTFile3 <<
"Nothing to report for missing changes of direction\n\n";
18889 SequenceLog +=
"14\n";
18898 typedef std::list<AnsiString> TLocList;
18899 TLocList BackwardList, ForwardList;
18900 bool IntroLineNeeded =
true;
18901 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
18903 unsigned int cdtPosition = 9999;
18904 AnsiString cdtLocation =
"";
18905 bool FoundSameName =
false;
18906 MarkerList.clear();
18908 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
18911 BackwardList.clear();
18912 ForwardList.clear();
18916 (AVEntry.
Command ==
"Frh-sh"))
18918 if(MarkerList.empty())
18925 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
18927 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
18929 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
18933 if(IntroLineNeeded)
18935 TTFile3 <<
"Questionable change of direction analysis.\n\n";
18936 TTFile3 <<
"For marked changes of direction there are no same-name locations listed both above (up to the start or another direction change)\n";
18937 TTFile3 <<
"and below (down to the end or another direction change) but not counting the change of direction location itself.\n\n";
18938 TTFile3 <<
"These changes of direction are probably valid for movements to and from depots but all should be checked to\n";
18939 TTFile3 <<
"make sure that none has been included incorrectly:\n\n";
18940 IntroLineNeeded =
false;
18942 TTFile3 <<
"Service sequence " << Sequence <<
" contains questionable changes of direction:-\n\n";
18954 for(
int z = y - 1; z >= 0; z--)
18957 if(AVEntry2.
Command ==
"cdt")
18966 BackwardList.sort();
18967 BackwardList.unique();
18968 for(
unsigned int z = y + 1; z < TDEntry.
ActionVector.size(); z++)
18982 ForwardList.sort();
18983 ForwardList.unique();
18984 FoundSameName =
false;
18986 if(!BackwardList.empty() && !ForwardList.empty())
18988 for(TLocList::iterator BLIt = BackwardList.begin(); BLIt != BackwardList.end(); BLIt++)
18990 for(TLocList::iterator FLIt = ForwardList.begin(); FLIt != ForwardList.end(); FLIt++)
18994 FoundSameName =
true;
19001 MarkerList.push_back(cdtPosition);
19005 if(IntroLineNeeded)
19007 TTFile3 <<
"Nothing to report for questionable changes of direction\n\n";
19023 SequenceLog +=
"15\n";
19029 catch(
const Exception &e)
19031 AnsiString TTErrorFileName =
"Analysis Error.txt";
19032 TTErrorFileName = CurDir +
"\\Formatted timetables\\" + TTErrorFileName;
19033 std::ofstream TTError(TTErrorFileName.c_str());
19036 ShowMessage(
"Analysis error file failed to open - can't be created");
19040 AnsiString TimeNow = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
19041 TTError << TimeNow.c_str() <<
'\n' << ArrRange <<
'\n' << ArrChecked <<
'\n' << DepRange <<
'\n' <<
19042 DepChecked <<
'\n' << AtLocChecked <<
'\n' << SequenceLog <<
'\n' << AnsiString(e.Message);
19045 ShowMessage(
"Error in Conflict Analysis: A file called 'Analysis Error.txt' has been created in your Formatted timetables folder. Please send this file together with your railway and timetable files to railwayfeedback@gmail.com for investigation - many thanks");
19055 if((SSVectorNumber < 0) || ((
unsigned int)SSVectorNumber >= SingleServiceVector.size()))
19057 throw Exception(
"SSVectorNumber out of range, = " + AnsiString(SSVectorNumber) +
", Vector size = " + SingleServiceVector.size());
19059 TTrainDataEntry SingleService = SingleServiceVector.at(SSVectorNumber);
19061 VecFile <<
",Initial service reference " << SingleService.
ServiceReference +
'\n';
19062 AnsiString Marker =
"";
19063 for(
unsigned int x = 0; x < SingleService.
ActionVector.size(); x++)
19066 for(
TNumListIterator MLIt = MarkerList.begin(); MLIt != MarkerList.end(); MLIt++)
19068 if(
int(x) == *MLIt)
19098 if(AVE.
Command.SubString(1,3) ==
"chr")
19107 AVE.
Command =
"Change of service to ";
19109 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"Fns-sh")
19111 AVE.
Command =
"Change to shuttle finishing service";
19113 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"F-nshs")
19140 AnsiString ListOfExits =
"";
19149 VecFile << Marker <<
"Frh" <<
'\n';
19164 for(
unsigned int x = 0; x < Vector.size(); x++)
19168 if(Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1).FormatType ==
Repeat)
19170 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 2);
19173 FinishType =
false;
19178 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1);
19181 FinishType =
false;
19186 return(Vector.at(x));
19190 return(Vector.at(Vector.size() - 1));
19199 if((Time1 ==
"") || (Time2 ==
""))
19204 int Mins = Time1.SubString(4,2).ToInt();
19205 int Hours = Time1.SubString(1,2).ToInt();
19206 int Time1Mins = (Hours * 60) + Mins;
19207 Mins = Time2.SubString(4,2).ToInt();
19208 Hours = Time2.SubString(1,2).ToInt();
19209 int Time2Mins = (Hours * 60) + Mins;
19210 if(abs(Time1Mins - Time2Mins) <= MinuteRange)
19222 bool &AnalysisError,
int &MaxNumberOfSameDirections)
19229 AnsiString Output =
"", OneService =
"", TempStr1 =
"", TempStr2 =
"";
19231 std::list<AnsiString> ServiceList;
19233 bool EvenComma =
false;
19234 for(
int x = 1; x <= Input.Length(); x++)
19236 TempStr1 = Input[x];
19237 if(TempStr1 == AnsiString(
',') && EvenComma)
19243 TempStr2 += Input[x];
19245 if(TempStr1 == AnsiString(
','))
19247 EvenComma = !EvenComma;
19251 while(TempStr2.Length() > 0)
19253 SCPos = TempStr2.Pos(
';');
19256 OneService = TempStr2.SubString(1, SCPos - 1);
19257 ServiceList.push_back(OneService);
19258 TempStr2 = TempStr2.SubString(SCPos + 1, TempStr2.Length() - SCPos);
19262 ServiceList.push_back(TempStr2);
19266 ServiceList.sort();
19267 ServiceList.unique();
19268 NumTrainsAtLoc = ServiceList.size();
19271 int DirectionMarker = 0;
19273 std::list<AnsiString>::iterator SLIt, SLIt1, SLIt2, SLIt3;
19275 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
19277 *SLIt = *SLIt +
"&0";
19279 SLIt3 = ServiceList.end();
19281 AnsiString ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatInfo1, RepeatInfo2;
19282 int AmpersandPos, SpacePos, CommaPos1, CommaPos2, RepeatNum1, RepeatNum2;
19283 TAllServiceCallingLocsMap::iterator ASCLIt1, ASCLIt2;
19285 MaxNumberOfSameDirections = 0;
19286 int SameDirectionCount = 0;
19288 for(std::list<AnsiString>::iterator SLIt1 = ServiceList.begin(); SLIt1 != SLIt3; SLIt1++)
19292 if(SLIt1->SubString(SLIt1->Length() - 1, 2) != AnsiString(
"&0"))
19298 CommaPos1 = SLIt1->Pos(
',');
19299 ServiceRef1 = SLIt1->SubString(1, CommaPos1 - 1);
19301 SpacePos = ServiceRef1.Pos(
' ');
19305 RepeatInfo1 = ServiceRef1.SubString(SpacePos + 2, ServiceRef1.Length() - SpacePos - 2);
19306 ServiceRef1 = ServiceRef1.SubString(1, SpacePos - 1);
19307 if(RepeatInfo1[1] ==
'F')
19313 SpacePos = RepeatInfo1.Pos(
' ');
19314 RepeatNum1 = RepeatInfo1.SubString(SpacePos + 1, RepeatInfo1.Length() - SpacePos).ToInt();
19317 AnsiTime1 = SLIt1->SubString(CommaPos1 + 1, SLIt1->Length() - CommaPos1);
19319 AmpersandPos = AnsiTime1.Pos(
'&');
19320 AnsiTime1 = AnsiTime1.SubString(1, AmpersandPos - 1);
19325 throw Exception(
"ASCLIt1 Error in " + Input);
19327 ServiceCallingLocsList1 = ASCLIt1->second;
19328 AmpersandPos = SLIt1->Pos(
'&');
19329 *SLIt1 = SLIt1->SubString(1, AmpersandPos);
19330 *SLIt1 = *SLIt1 + AnsiString(++DirectionMarker);
19332 SameDirectionCount = 1;
19333 for(SLIt2 = SLIt; SLIt2 != ServiceList.end(); SLIt2++)
19335 CommaPos2 = SLIt2->Pos(
',');
19336 ServiceRef2 = SLIt2->SubString(1, CommaPos2 - 1);
19338 SpacePos = ServiceRef2.Pos(
' ');
19342 RepeatInfo2 = ServiceRef2.SubString(SpacePos + 2, ServiceRef2.Length() - SpacePos - 2);
19343 ServiceRef2 = ServiceRef2.SubString(1, SpacePos - 1);
19344 if(RepeatInfo2[1] ==
'F')
19350 SpacePos = RepeatInfo2.Pos(
' ');
19351 RepeatNum2 = RepeatInfo2.SubString(SpacePos + 1, RepeatInfo2.Length() - SpacePos).ToInt();
19354 AnsiTime2 = SLIt2->SubString(CommaPos2 + 1, SLIt2->Length() - CommaPos2);
19356 AmpersandPos = AnsiTime2.Pos(
'&');
19357 AnsiTime2 = AnsiTime2.SubString(1, AmpersandPos - 1);
19362 throw Exception(
"ASCLIt2 Error in " + Input);
19364 ServiceCallingLocsList2 = ASCLIt2->second;
19366 if(
SameDirection(0, ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatNum1, RepeatNum2, ServiceCallingLocsList1, ServiceCallingLocsList2, Location, Arrival))
19368 int AmpersandPos = SLIt2->Pos(
'&');
19369 *SLIt2 = SLIt2->SubString(1, AmpersandPos);
19370 *SLIt2 = *SLIt2 + AnsiString(DirectionMarker);
19371 SameDirectionCount++;
19374 if(SameDirectionCount > MaxNumberOfSameDirections)
19376 MaxNumberOfSameDirections = SameDirectionCount;
19381 if(SLIt3->SubString(SLIt3->Length() - 1, 2) == AnsiString(
"&0"))
19384 AmpersandPos = SLIt3->Pos(
'&');
19385 *SLIt3 = SLIt3->SubString(1, AmpersandPos);
19386 *SLIt3 = *SLIt3 + AnsiString(++DirectionMarker);
19389 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
19392 AmpersandPos = SLIt->Pos(
'&');
19393 AnsiString DirectionMarkerString = SLIt->SubString(AmpersandPos + 1, SLIt->Length() - AmpersandPos);
19394 AnsiString ServiceWithoutMarker = SLIt->SubString(1, AmpersandPos - 1);
19395 DirectionMarker = DirectionMarkerString.ToInt();
19396 AnsiString DirectionSuffix =
"";
19398 if(DirectionMarker < 27)
19400 c = 64 + DirectionMarker;
19401 DirectionSuffix =
"," + AnsiString(c);
19403 else if(DirectionMarker < 53)
19405 c = 65 + DirectionMarker - 27;
19406 DirectionSuffix =
",A" + AnsiString(c);
19410 DirectionSuffix =
",?";
19412 *SLIt = ServiceWithoutMarker + DirectionSuffix;
19415 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
19417 Output = Output + *SLIt +
",";
19419 if(Output.Length() > 0)
19421 Output = Output.SubString(1, Output.Length() - 1);
19427 catch(
const Exception &e)
19429 AnalysisError =
true;
19441 AnsiString InternalInput = Input, Output =
"", OneService =
"";
19443 std::list<AnsiString> ServiceList;
19445 while(InternalInput.Length() > 0)
19447 CommaPos = InternalInput.Pos(
',');
19450 OneService = InternalInput.SubString(1, CommaPos - 1);
19451 ServiceList.push_back(OneService);
19452 InternalInput = InternalInput.SubString(CommaPos + 1, InternalInput.Length() - CommaPos);
19456 ServiceList.push_back(InternalInput);
19457 InternalInput =
"";
19461 ServiceList.sort();
19462 ServiceList.unique();
19463 NumTrainsAtLoc = ServiceList.size();
19464 for(std::list<AnsiString>::iterator SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
19466 Output = Output + *SLIt +
",";
19468 if(Output.Length() > 0)
19470 Output = Output.SubString(1, Output.Length() - 1);
19483 AnsiString(RepeatNum1) +
"," + AnsiString(RepeatNum2) +
"," + Location);
19485 std::list<AnsiString>::iterator LP1 = 0, LP2 = 0, ListPtr1 = 0, ListPtr2 = 0, LocPtr1 = 0, LocPtr2 = 0;
19490 bool LocFound =
false;
19491 AnsiString Ref1 = Ref1In, Ref2 = Ref2In;
19493 TDateTime FirstServiceTime;
19496 int Ref1Target = 0, Ref1Count = 0;
19497 int SlashPos = Ref1.Pos(
'/');
19500 Ref1Target = Ref1.SubString(SlashPos + 1, Ref1.Length() - SlashPos).ToInt();
19501 Ref1 = Ref1.SubString(1, SlashPos - 1);
19503 int Ref2Target = 0, Ref2Count = 0;
19504 SlashPos = Ref2.Pos(
'/');
19507 Ref2Target = Ref2.SubString(SlashPos + 1, Ref2.Length() - SlashPos).ToInt();
19508 Ref2 = Ref2.SubString(1, SlashPos - 1);
19510 for(ListPtr1 = List1.begin(); ListPtr1 != List1.end(); ListPtr1++)
19513 if((*ListPtr1) == Location)
19515 LocPtr1 = ListPtr1;
19518 if(ListPtr1->SubString(1, 3) ==
"%%%")
19520 AnsiString CDTTime = ListPtr1->SubString(4, 5);
19525 FirstServiceTime = TDateTime(-1);
19526 bool BreakFlag =
false;
19529 if(TDVIt->ServiceReference == Ref1)
19531 if(Ref1Target > Ref1Count)
19536 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
19537 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
19541 FirstServiceTime = AVIt->EventTime;
19547 FirstServiceTime = AVIt->ArrivalTime;
19553 FirstServiceTime = AVIt->DepartureTime;
19564 if(IncMinutes == -1)
19566 throw Exception(
"Failed to find service for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
19568 if(FirstServiceTime == TDateTime(-1))
19570 throw Exception(
"Failed to find first service time for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
19574 if(!Arrival && (Time1 == CDTTime))
19579 if(Arrival && (Time1 == CDTTime))
19583 if(Time1 > CDTTime)
19588 if(Time1 < CDTTime)
19601 for(ListPtr2 = List2.begin(); ListPtr2 != List2.end(); ListPtr2++)
19603 if((*ListPtr2) == Location)
19605 LocPtr2 = ListPtr2;
19608 if(ListPtr2->SubString(1, 3) ==
"%%%")
19610 AnsiString CDTTime = ListPtr2->SubString(4, 5);
19615 FirstServiceTime = TDateTime(-1);
19616 bool BreakFlag =
false;
19619 if(TDVIt->ServiceReference == Ref2)
19621 if(Ref2Target > Ref2Count)
19626 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
19627 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
19631 FirstServiceTime = AVIt->EventTime;
19637 FirstServiceTime = AVIt->ArrivalTime;
19643 FirstServiceTime = AVIt->DepartureTime;
19654 if(IncMinutes == -1)
19656 throw Exception(
"IncMinutes -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
19658 if(FirstServiceTime == TDateTime(-1))
19660 throw Exception(
"First service time -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
19664 if(!Arrival && (Time2 == CDTTime))
19669 if(Arrival && (Time2 == CDTTime))
19673 if(Time2 > CDTTime)
19678 if(Time2 < CDTTime)
19693 LP1 = List1.begin();
19695 for(ListPtr1 = LocPtr1; ListPtr1 != LP1; ListPtr1--)
19697 if(ListPtr1 == List1.begin())
19701 if(ListPtr1->SubString(1, 3) ==
"%%%")
19708 LP2 = List2.begin();
19710 for(ListPtr2 = LocPtr2; ListPtr2 != LP2; ListPtr2--)
19712 if(ListPtr2 == List2.begin())
19716 if(ListPtr2->SubString(1, 3) ==
"%%%")
19726 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
19728 if(ListPtr1 == LocPtr1)
19732 if(ListPtr1->SubString(1, 3) ==
"%%%")
19736 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
19738 if(ListPtr2 == LocPtr2)
19742 if(ListPtr2->SubString(1, 3) ==
"%%%")
19746 if((*ListPtr1) == (*ListPtr2))
19763 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
19765 if(ListPtr1 == List1.end())
19769 if(ListPtr1->SubString(1, 3) ==
"%%%")
19773 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
19775 if(ListPtr2 == List2.end())
19779 if(ListPtr2->SubString(1, 3) ==
"%%%")
19783 if((*ListPtr1) == (*ListPtr2))
19800 if(ExitList.empty())
19806 AnsiString ExitLocList =
"";
19809 unsigned int Counter = 0;
19810 for(
TNumListIterator ELIt = ExitList.begin(); ELIt != ExitList.end(); ELIt++)
19814 if(((Counter % 6) == 0) && (Counter < (ExitList.size() - 1)))
19816 ExitLocList +=
"\n";
19819 if(StartName ==
"")
19821 if(ExitList.size() == 1)
19825 return(
" at " + ID);
19830 if(ExitList.size() < 4)
19832 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
19837 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
19842 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
19847 if(ExitList.size() < 4)
19849 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
19854 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
19860 if(ExitList.size() < 4)
19862 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
19863 return(
" at " + StartName);
19867 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
19868 return(
" at " + StartName);
19908 AnsiString FormatStr =
"####0.0";
19909 AnsiString AvLateArrMins =
"";
19910 AnsiString AvEarlyArrMins =
"";
19911 AnsiString AvLatePassMins =
"";
19912 AnsiString AvEarlyPassMins =
"";
19913 AnsiString AvLateDepMins =
"";
19914 AnsiString AvLateExitMins =
"";
19915 AnsiString AvEarlyExitMins =
"";
19918 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
19951 PerfFile <<
'\n' <<
'\n' <<
"***************************************";
19952 PerfFile <<
'\n' <<
'\n' <<
"Performance summary:" <<
'\n';
19964 PerfFile <<
LateArrivals <<
" late arrivals (average " << AvLateArrMins.c_str() <<
" min)" <<
'\n';
19968 PerfFile <<
LateArrivals <<
" late arrival (" << AvLateArrMins.c_str() <<
" min)" <<
'\n';
19976 PerfFile <<
EarlyArrivals <<
" early arrivals (average " << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
19980 PerfFile <<
EarlyArrivals <<
" early arrival (" << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
19988 PerfFile <<
OnTimePasses <<
" on-time passes" <<
'\n';
19996 PerfFile <<
LatePasses <<
" late passes (average " << AvLatePassMins.c_str() <<
" min)" <<
'\n';
20000 PerfFile <<
LatePasses <<
" late pass (" << AvLatePassMins.c_str() <<
" min)" <<
'\n';
20004 PerfFile <<
LatePasses <<
" late passes" <<
'\n';
20008 PerfFile <<
EarlyPasses <<
" early passes (average " << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
20012 PerfFile <<
EarlyPasses <<
" early pass (" << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
20016 PerfFile <<
EarlyPasses <<
" early passes" <<
'\n';
20021 PerfFile <<
OnTimeExits <<
" on-time exits" <<
'\n';
20025 PerfFile <<
OnTimeExits <<
" on-time exit" <<
'\n';
20029 PerfFile <<
LateExits <<
" late exits (average " << AvLateExitMins.c_str() <<
" min)" <<
'\n';
20033 PerfFile <<
LateExits <<
" late exit (" << AvLateExitMins.c_str() <<
" min)" <<
'\n';
20037 PerfFile <<
LateExits <<
" late exits" <<
'\n';
20041 PerfFile <<
EarlyExits <<
" early exits (average " << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
20045 PerfFile <<
EarlyExits <<
" early exit (" << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
20049 PerfFile <<
EarlyExits <<
" early exits" <<
'\n';
20054 PerfFile <<
OnTimeDeps <<
" on-time departures" <<
'\n';
20058 PerfFile <<
OnTimeDeps <<
" on-time departure" <<
'\n';
20062 PerfFile <<
LateDeps <<
" late departures (average " << AvLateDepMins.c_str() <<
" min)" <<
'\n';
20066 PerfFile <<
LateDeps <<
" late departure (" << AvLateDepMins.c_str() <<
" min)" <<
'\n';
20070 PerfFile <<
LateDeps <<
" late departures" <<
'\n';
20072 TDateTime TempExcessLCDownTime;
20086 if(TempExcessLCDownTime > TDateTime(0))
20092 AnsiString FormattedExcessLCDownMins = FormatFloat(FormatStr,
ExcessLCDownMins);
20096 PerfFile << FormattedExcessLCDownMins.c_str() <<
" excess minutes of level crossing barrier down time" <<
'\n';
20104 PerfFile <<
MissedStops <<
" missed stops" <<
'\n';
20108 PerfFile <<
MissedStops <<
" missed stop" <<
'\n';
20144 PerfFile <<
NumFailures <<
" train failures" <<
'\n';
20148 PerfFile <<
NumFailures <<
" train failure" <<
'\n';
20154 PerfFile <<
AvHoursIntValue <<
" hour mean time betweeen train failures" <<
'\n';
20158 PerfFile <<
AvHoursIntValue <<
" hours mean time betweeen train failures" <<
'\n';
20161 AnsiString AvLateMinsLocsNotReached =
"";
20167 if(LocsNotReached > 0)
20170 PerfFile << LocsNotReached <<
" locations that trains failed to reach (average lateness " << AvLateMinsLocsNotReached.c_str() <<
" min)" <<
'\n';
20174 PerfFile <<
SPADRisks <<
" SPAD risks" <<
'\n';
20178 PerfFile <<
SPADRisks <<
" SPAD risk" <<
'\n';
20190 PerfFile <<
Derailments <<
" derailments" <<
'\n';
20194 PerfFile <<
Derailments <<
" derailment" <<
'\n';
20204 PerfFile <<
'\n' <<
"***************************************" <<
'\n';
20206 bool DerailSPADFlag =
false, CrashFlag =
false;
20208 int OverallScorePercent = 100;
20209 int TotArrDepExit = 0;
20210 double TotLateMinsFactor = 1;
20211 double MissedStopAndSPADRiskFactor = 1;
20212 double NetNegFactor = 1;
20222 OverallScorePercent = 5;
20223 DerailSPADFlag =
true;
20227 OverallScorePercent = 0;
20230 if(OverallScorePercent == 100)
20235 LatenessPenalty = 0;
20241 if(TotArrDepExit > 0)
20250 NetNegFactor = TotLateMinsFactor * MissedStopAndSPADRiskFactor;
20252 OverallScorePercent = 100 * NetNegFactor;
20255 if((TotArrDepExit > 0) || DerailSPADFlag || CrashFlag)
20258 AnsiString OneFailureString =
", though the failure would account for some poor performance";
20259 AnsiString TwoOrMoreFailureString =
", though the failures would account for some poor performance";
20260 AnsiString AddedString =
"";
20263 AddedString = OneFailureString;
20267 AddedString = TwoOrMoreFailureString;
20269 PerfFile <<
"\nOverall score: " << OverallScorePercent <<
"%\n";
20270 AnsiString Rating =
"";
20271 if(OverallScorePercent == 100)
20273 Rating =
"Perfect!";
20275 else if(OverallScorePercent >= 95)
20277 Rating =
"Excellent";
20279 else if(OverallScorePercent >= 90)
20281 Rating =
"Very good";
20283 else if(OverallScorePercent >= 80)
20287 else if(OverallScorePercent >= 70)
20291 else if(OverallScorePercent >= 60)
20293 Rating =
"Unacceptable" + AddedString;
20295 else if(OverallScorePercent >= 50)
20297 Rating =
"Poor" + AddedString;
20299 else if(OverallScorePercent >= 40)
20301 Rating =
"Bad" + AddedString;
20303 else if(OverallScorePercent >= 30)
20305 Rating =
"Very bad" + AddedString;
20307 else if(OverallScorePercent >= 20)
20309 Rating =
"Terrible" + AddedString;
20311 else if(OverallScorePercent >= 10)
20313 Rating =
"Appalling" + AddedString;
20315 else if(OverallScorePercent >= 5)
20319 Rating =
"Disastrous - potential loss of life";
20324 Rating =
"Dire" + AddedString;
20327 else if(OverallScorePercent < 5)
20331 Rating =
"Catastrophic - loss of life";
20335 Rating =
"Abysmal";
20338 PerfFile <<
"Overall rating: " << Rating.c_str() <<
'\n';
20342 PerfFile <<
"\nThere were no timetabled departures, arrivals or exits so there is insufficient information to provide a performance score or rating" <<
'\n';
20344 PerfFile <<
'\n' <<
"***************************************";
20354 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
20404 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
20439 int IncrementalMinutes = 0;
20453 bool TrainOperatingFlag =
false;
20458 TrainOperatingFlag =
true;
20462 if(TrainOperatingFlag)
20470 for(
unsigned int z = 0; z < TDEntry.
ActionVector.size(); z++)
20517 AnsiString HeadCode;
20521 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
20525 HCandTrainPosParam.first = HeadCode;
20526 HCandTrainPosParam.second = TrainID;
20528 if((TimeToAct >= 0) && (TimeToAct < 59.9))
20531 OpTimeToActMultiMapEntry.first = TimeToAct;
20532 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
20561 float TimeToAct = 0;
20562 int DistanceToRedSignal = 0;
20565 ContinuationEntryVecPosVector.clear();
20566 bool LaterTrain =
false;
20570 LaterTrain =
false;
20571 if(CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry !=
NotStarted)
20582 if(!ContinuationEntryVecPosVector.empty())
20584 for(
unsigned int x = 0; x < ContinuationEntryVecPosVector.size(); x++)
20586 if(CTEIt->second.VectorPosition == ContinuationEntryVecPosVector.at(x))
20600 ContinuationEntryVecPosVector.push_back(CTEIt->second.VectorPosition);
20601 AnsiString HeadCode = CTEIt->second.HeadCode;
20602 float CurrentStopTime;
20603 float LaterStopTime;
20604 float RecoverableTime;
20607 int DistanceToExit;
20609 bool SigControlAndCanPassRedSignal =
false;
20617 if(CTEIt->second.TrainDataEntryPtr->ActionVector.size() == 1)
20623 SigControlAndCanPassRedSignal, &CTEIt->second.TrainDataEntryPtr->ActionVector.at(AtValue),
20624 HeadCode, TrainID, CurrentStopTime, LaterStopTime, RecoverableTime, AvTrackSpeed, DistanceToExit, ExitPair);
20627 if(AvTrackSpeed < 30)
20631 if(DistanceToRedSignal == -1)
20637 int Speed = AvTrackSpeed;
20638 int MaxSpeed = int(CTEIt->second.TrainDataEntryPtr->MaxRunningSpeed);
20639 if(AvTrackSpeed > MaxSpeed)
20643 if(CTEIt->second.TrainDataEntryPtr->ActionVector.at(0).SignallerControl)
20646 Speed = CTEIt->second.TrainDataEntryPtr->SignallerSpeed;
20649 TimeToAct = LaterStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
20654 float MinsBefEnter = double(CTEIt->first -
TTClockTime) * 86400.0 / 60.0;
20655 TimeToAct += MinsBefEnter;
20658 HCandTrainPosParam.first = HeadCode;
20659 HCandTrainPosParam.second = -1 - CTEIt->second.VectorPosition;
20662 if(TimeToAct < 59.9)
20664 OpTimeToActMultiMapEntry.first = TimeToAct;
20665 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
20690 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
20700 TimeToExitMultiMapEntry.first = ExitPair;
20701 TimeToExitMultiMapEntry.second = ExitInfo;
20711 bool SigControlAndCanPassRedSignal,
TActionVectorEntry *AVPtr, AnsiString HeadCode,
int TrainID,
float &CurrentStopTime,
float &LaterStopTime,
20712 float &RecoverableTime,
int &AvTrackSpeed,
int &DistanceToExit,
THVShortPair &ExitPair)
20721 AnsiString(TrackVectorPositionEntryPos) +
", " + AVPtr->
Command);
20722 int DistanceToRedSignal = 0;
20723 DistanceToExit = -1;
20724 ExitPair.first = -1;
20725 ExitPair.second = -1;
20726 int CumTrackSpeed = 0;
20728 int TrackSpeedCount = 0;
20729 float KmPerLocationStop;
20730 float MaxAllowableSpeed;
20740 int CurrentElement = TrackVectorPosition;
20741 int CurrentEntryPos = TrackVectorPositionEntryPos;
20746 CurrentStopTime = 0;
20748 RecoverableTime = 0;
20749 if(CurrentElement == -1)
20754 int CurrentExitPos;
20759 if((CurrentEntryPos == 0) || (CurrentEntryPos == 2))
20763 CurrentExitPos = 1;
20767 CurrentExitPos = 3;
20772 CurrentExitPos = 0;
20809 CurrentStopTime = float(TimeToDepart);
20815 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
20826 else if(SigControlAndCanPassRedSignal)
20831 if((NextEntryPos == 0) || (NextEntryPos == 2))
20852 CurrentElement = NextElement;
20853 CurrentEntryPos = NextEntryPos;
20854 CurrentExitPos = NextExitPos;
20866 int LaterStopNumber = 0;
20870 while(!((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0)))
20879 if(CurrentEntryPos > 1)
20894 DistanceToExit = DistanceToRedSignal;
20899 if(TrackSpeedCount > 0)
20901 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
20905 if(CurrentEntryPos > 1)
20916 if(LaterStopNumber > 0)
20918 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
20919 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
20925 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
20929 if(AvTrackSpeed > MaxAllowableSpeed)
20931 AvTrackSpeed = MaxAllowableSpeed;
20943 bool StopRequired =
false;
20960 int TrainOnElement;
20967 if(CurrentEntryPos > 1)
20976 if((TrainOnElement > -1) && (TrainOnElement != TrainID))
20985 double StopTimeDouble;
20998 if(StopTimeDouble < 0.5)
21000 StopTimeDouble = 0.5;
21004 LaterStopTime += float(StopTimeDouble);
21005 RecoverableTime += StopTimeDouble - 0.5;
21006 if((LaterStopNumber == 1) && (TrainID > -1))
21014 if((AVPtr + 1)->FormatType ==
TimeLoc)
21018 StopTimeDouble = double((AVPtr + 1)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
21020 if(StopTimeDouble < 0.5)
21022 StopTimeDouble = 0.5;
21025 LaterStopTime += float(StopTimeDouble);
21026 RecoverableTime += StopTimeDouble - 0.5;
21027 if((LaterStopNumber == 1) && (TrainID > -1))
21043 if(NextElement == -1)
21052 if((NextEntryPos == 0) || (NextEntryPos == 2))
21073 CurrentElement = NextElement;
21074 CurrentEntryPos = NextEntryPos;
21075 CurrentExitPos = NextExitPos;
21080 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
21093 if(TrackSpeedCount > 0)
21095 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
21099 if(CurrentEntryPos > 1)
21110 if(LaterStopNumber > 0)
21112 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
21113 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
21119 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
21123 if(AvTrackSpeed > MaxAllowableSpeed)
21125 AvTrackSpeed = MaxAllowableSpeed;
21128 return(DistanceToRedSignal);